Conscription POJ

来源:互联网 发布:转行做网络运营 编辑:程序博客网 时间:2024/05/22 14:06

点击打开链接

虽是二分图 但在此题中男女其实可以看做同一类型 都是点与点之间的关系

两人之间的关系价值就是边长 用这些边凑最大生成树(边长就是优惠值 优惠越多越好) 虽然有可能不是一颗完整的生成树

个人感觉题意中比较难理解的就是 "Notice that only one relationship can be used when collecting one soldier."

一开始觉得这个条件与生成树相矛盾:一个点的所有相关联的边只能选其一 根本无法形成连通图

其实就是当两点之间有多个关系时只能用其中一个 样例中就有

至于为什么是一棵树而不能形成回路 比如a--b--c--d四人 a参军影响b b参军影响c c参军影响d 此时a已参军 d无法影响a 构不成回路

#include <stdio.h>#include <algorithm>using namespace std;struct node{    int u;    int v;    long long w;};struct node edge[50001];int f[20001];int n,m;int cmp(node n1,node n2){    return n1.w>n2.w;}int unite(int u,int v);int getf(int p);int main(){    long long w,sum;    int t,i,j,u,v,n1,n2,cnt;    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n1,&n2,&m);        n=n1+n2;        for(i=1;i<=m;i++)        {            scanf("%d%d%lld",&u,&v,&w);            u++,v++;            u+=n2;            edge[i].u=u,edge[i].v=v,edge[i].w=w;        }        sort(edge+1,edge+m+1,cmp);        for(i=1;i<=n;i++)        {            f[i]=i;        }        cnt=0,sum=0;        for(i=1;i<=m;i++)        {            if(unite(edge[i].u,edge[i].v))            {                sum+=edge[i].w;                cnt++;            }            if(cnt==n-1) break;        }        sum=n*10000-sum;        printf("%lld\n",sum);    }    return 0;}int unite(int u,int v){    int fu,fv;    fu=getf(u);    fv=getf(v);    if(fu!=fv)    {        f[fv]=fu;        return 1;    }    else return 0;}int getf(int p){    if(f[p]==p) return p;    else    {        f[p]=getf(f[p]);        return f[p];    }}

原创粉丝点击