poj 3723

来源:互联网 发布:薄洗来 知乎 编辑:程序博客网 时间:2024/05/14 04:55

题意:

想要征m个女兵,n个男兵。每个兵需要10000。但是若兵是恋情关系,且他们的恋情是有价格的,那么征另一名与他(她)有关系的兵,只需10000 - x(他们的价值)。

这个题明显最大生成树,我们把恋人的关系看成有权值的边。那么我们要找的是由这些边组成的最大的生成森林。需要注意的是不能有环,也就是,不能重复边(每个人可能有多种关系,且可能关系重复)。

#include<iostream>#include<algorithm>#include<cstdio>using namespace std;const int maxn = 5 * 10000 + 10;const int N = 10000;struct node{    int x, y, cost;    node(int a, int b, int c): x(a), y(b), cost(c){}    node(){}    bool operator < (const node &a) const    {        return cost > a.cost;    }}e[maxn];int par[2 * 10000 + 5];int root(int x){    if(par[x] != x)    {        par[x] = root(par[x]);    }    return par[x];}void unite(int a, int b){    par[root(a)] = root(b);}bool same(int a, int b){    if(root(a) == root(b)) return true;    return false;}int Kruskal(int n){    int ret = 0;    sort(e, e + n);    for(int i = 0; i < n; i++)    {        //printf("yes\n");        if(!same(e[i].x, e[i].y + N))        {            unite(e[i].x, e[i].y + N);            ret += e[i].cost;        }    }    return ret;}int main(){    int T;    scanf("%d", &T);    for(int kase = 1; kase <= T; kase++)    {        int m, n, l;        scanf("%d%d%d", &m, &n, &l);        //printf("%d %d %d\n", m, n, l);        for(int i = 0; i <= m; i++)            par[i] = i;        for(int i = N; i <= N + n; i++)            par[i] = i;        //printf("yes\n");        for(int i = 0; i < l; i++)        {            //printf("%d\n", i);            int u, v, c;            scanf("%d%d%d", &u, &v, &c);            e[i] = node(u, v, c);        }        printf("%d\n", (m + n) * 10000 - Kruskal(l));    }    return 0;}


原创粉丝点击