zoukankan      html  css  js  c++  java
  • poj3723,最 大 生成树

    Conscription
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 8243   Accepted: 2859

    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, NM and R.
    Then R lines followed, each contains three integers xiyi and di.
    There is a blank line before each test case.

    1 ≤ NM ≤ 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
    

    Source

    这道题我从上午10点多开始做,到现在下午快三点了才AC。

    好把,这回要认真写解题报告了!!!

    大意:韦小宝为了反清复明打算征兵,但是他没有权势,所以只能花钱,征一个兵给人家10000RMB(先不讨论为什么是RMB吧)。韦爵爷多聪明的人啊,心里盘算着能不能省点,正好被他发现了一个省钱的方法。爵爷发现,只要把男丁喜欢的人招进来,那么想招这个男丁就只需要花10000-d,其中d是物质化了的此男对女的爱慕程度,同样,这个规律也适应于女丁。好,here is the question:爵爷该咋的才能花最少的钱招这写人呢???

    有N男M女,既然是花最少的钱,何不利用最小生成树,将权值设为10000-d,直接kruskal一下。

    嗯,这个想法是正确的,但是有漏洞。因为kruscal算法默认的是所有节点连通,但是这里的男女关系很可能是森林,,,你想想,假如这里的男女关系是连通的,可以构成一颗最小生成树,那,哇,这个村庄里的男女关系好复杂啊,哈哈。

    那正确的解题思路是:求出所有的最大连通子图的权值和sum,然后用10000*(N+M)-sum。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 10000
    #define maxr 50005
    #define maxnr maxn+maxr+10
    int n, m, r, tot;        //1 ≤ N, M ≤ 10000
    struct edge{ 
        int from, to, c; 
        edge(){
            c = maxn;  //初始化c=maxn的目的就是因为利用并查集时,我直接把男、女放在一个数组par中,
        }          //女的下标是从maxn+i开始的
    }cost[maxr * 2];
    bool cmp(edge a, edge b){ return a.c > b.c; }
    int par[maxr*2], k;        //并查集    
    
    int find(int x){    
        int r = x;
        while (par[r] != r)r = par[r];
        int i = x, j;
        while (par[i] != r){
            j = par[i];
            par[i] = r;
            i = j;
        }
        return r;
    }
    void unite(int x, int y){
        x = find(x); y = find(y);
        par[x] = par[y];
    }
    bool same(int x, int y){
        x = find(x); y = find(y);
        return x == y;
    }
    
    inline void init(){
        for (int i = 0; i < maxr*2; i++)par[i] = i;
        tot = 0;
        k = 0;
        int x, y, d;
        for (int i = 0; i < r; i++){
            scanf("%d %d %d", &x, &y, &d);
            cost[++k].from = x; cost[k].to = maxn + y; cost[k].c = d;//
            cost[++k].from = maxn + y; cost[k].to = x; cost[k].c = d;//look,从这里我就加了个偏移量maxn,并查集就可以用了
        }
        sort(cost + 1, cost + k + 1, cmp);
    }
    
    void solve(){for (int i = 1; i <= k; i++){
            if (!same(cost[i].from, cost[i].to)){
                tot += cost[i].c;
                unite(cost[i].from, cost[i].to);
            }
        }
        printf("%d
    ", maxn*(n+m) - tot);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--){
            scanf("%d %d %d", &n, &m, &r);
            init();
            solve();
        }
    //    system("pause");
        return 0;
    }
    世上无难事,只要肯登攀。
  • 相关阅读:
    docker4dotnet #1 – 前世今生 & 世界你好
    DockerCon 2016 – 微软带来了什么?
    TFS 2015 敏捷开发实践 – 看板的使用
    几款Git GUI客户端工具
    (视频)Erich Gamma 与 Visual Studio Online 的一点野史
    GitHub + VSTS 开源代码双向同步
    UDAD 用户故事驱动的敏捷开发 – 演讲实录
    用户故事驱动的敏捷开发 – 2. 创建backlog
    算法 之 简单选择排序法
    算法 之 冒泡排序法
  • 原文地址:https://www.cnblogs.com/littlehoom/p/4211036.html
Copyright © 2011-2022 走看看