• 【最大生成树】Conscription


    Conscription
    Time Limit: 1000MS   Memory Limit: 65536K
         

    Description

    Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girl x and boy y have a relationship d and one of them has been collected, Windy can collect the other one with 10000-d RMB. Now given all the relationships between girls and boys, your assignment is to find the least amount of money Windy has to pay. Notice that only one relationship can be used when collecting one soldier.

    Input

    The first line of input is the number of test case.
    The first line of each test case contains three integers, N, M and R.
    Then R lines followed, each contains three integers xi, yi and di.
    There is a blank line before each test case.

    1 ≤ N, M ≤ 10000
    0 ≤ R ≤ 50,000
    0 ≤ xi < N
    0 ≤ yi < M
    0 < di < 10000

    Output

    For each test case output the answer in a single line.

    Sample Input

    2
    
    5 5 8
    4 3 6831
    1 3 4583
    0 0 6592
    0 1 3063
    3 3 4975
    1 3 2049
    4 2 2104
    2 2 781
    
    5 5 10
    2 4 9820
    3 2 6236
    3 1 8864
    2 4 8326
    2 0 5156
    2 0 1463
    4 1 2439
    0 4 4373
    3 4 8889
    2 4 3133
    

    Sample Output

    71071
    54223
    

    OJ:POJ

    题目大意

    需要征募女兵N人,男兵M人。每征募一个人需要花费10000美元。但是如果已经征募的人中有一些关系亲密的人,那么可以少花一些钱。给出若干的男女之间的1~19999之间的亲密度关系,征募某个人的费用是1000-(已经征募的人中和自己的亲密度的最大值)。要求通过适当的征募顺序使得征募所有人所需费用最小。输入的关系中x,y,d表示第x号男兵,第y号女兵,亲密度。

    分析

    征募人的时候尽可能找亲密度大的,即最大生成树问题,用征募N+M人的费用减去最大生成树的总权值即所需最小费用。

    参考代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    struct Edge{
    int x;
    int y;
    int weight;
    }edge[50001];
    int par[20001];
    int rank[20001];
    int vertex_num,arc_num,case_num;
    int N,M,R;
    int ans,sum;
    
    void init();
    int find(int x);
    bool unite(int x,int y);
    bool compare(const Edge &a,const Edge &b);
    void kruskal();
    
    int main()
    {
        scanf("%d",&case_num);
        while(case_num){
            sum=0;
            scanf("%d%d%d",&N,&M,&R);
            vertex_num=N+M;
            arc_num=R;
            for(int i=0;i<R;i++){
                scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].weight);
                edge[i].y+=N;//区别男女兵
            }
            kruskal();
            int ans=10000*vertex_num-sum;
            printf("%d
    ",ans);
            case_num--;
        }
    
        return 0;
    }
    
    void init(){
        for(int i=0;i<vertex_num;i++){
            par[i]=i;
            rank[i]=0;
        }
    
    }
    
    int find(int x){
    if(x==par[x])
        return x;
    else{
        return par[x]=find(par[x]);
    }
    }
    
    bool unite(int x,int y){
    int r1=find(x);
    int r2=find(y);
    if(r1==r2)
        return false;
    else{
        if(rank[r1]>rank[r2]){
            par[r2]=r1;
        }
        else if(rank[r1]<rank[r2]){
            par[r1]=r2;
        }
        else{
            par[r2]=r1;
            rank[r1]++;
        }
        return true;
    
        }
    }
    
    bool compare(const Edge &a,const Edge &b){
        return a.weight>b.weight;
    }
    
    void kruskal(){
        init();
        sort(edge,edge+arc_num,compare);
        for(int i=0;i<arc_num;i++){
            if(unite(edge[i].x,edge[i].y)){
                sum+=edge[i].weight;
            }
        }
    }

     

     

     

     

  • 相关阅读:
    试算平衡
    对账服务
    会计科目与账户
    支付系统难点全面梳理剖析:核算对账核心
    支付系统设计——你不可不知的会计核心(转发整理)
    支付系统设计之查漏补缺的一环:差错账处理
    支付清算业务总结
    财务对账系统v1.0立项到结项的整体回顾
    DNS视图及压力测试(四)
    一个快速检测系统CPU负载的小程序
  • 原文地址:https://www.cnblogs.com/LuRenJiang/p/7424194.html
Copyright © 2020-2023  润新知