Donald established a company. This company needs to employ M boys and N girls. The fee for employing one person is K RMB, but Donald finds that there exists a certain complex relationship between some boys and girls. The fee for employing can be decreased if this relationship can be fully made use of. Given the intensity of relationship between the ith boy and the jth girl is Rij, it needs the company K RMB to hire the ith boy or the jth girl first, and then it only needs (K- Rij) RMB to hire the jth girl or the ith boy.
All the X kinds of relationship between boys and girls are given and a person can be hired at most through one type of the relationship. Now, please help Donald to calculate the minimum expense he needs to spend to hire all the M boys and N girls.
首先我们需要把题目抽象成图论模型,把有关系的都连上一条边,因为只能对应一种关系,所以它不会存在环,是一颗树,这个从样例数据也也能分析道,最后的答案是K*所有人-R,R表示这颗树的边权,所以这是一道最大生成树问题。复杂度就是生成树的复杂度O(Mlog(M))
/************************************************************************* * author:crazy_石头 * algorithm:MST * date:2013/09/29 **************************************************************************/ #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAX 50000 struct data { int a,b,val; }x[MAX]; struct USFtree { int p,rank; }note[MAX*2]; void makeset(int m) //点的初始化 { note[m].p=m; note[m].rank=0; } int find(int m) //并查集,查找祖先节点 { while(m!=note[m].p) m=note[m].p; return m; } void union2(int m,int n) //并查集,两颗子树按秩合并;也可以路径压缩的; { m=find(m); n=find(n); if(n==m) return; else { if(note[n].rank>note[m].rank) note[m].p=n; else { note[n].p=m; if(note[n].rank==note[m].rank) note[m].rank++; } } } bool cmp(const data &a, const data &b) { return a.val>b.val; } int main() { int n,m,i,t,cas,k,r,cnt; scanf("%d",&cas); while(cas--) { memset(note,0,sizeof(note)); cnt=0; scanf("%d%d%d%d",&n,&m,&k,&r); for(i=0;i<r;i++) { scanf("%d%d%d",&x[i].a,&t,&x[i].val); x[i].b=t+n; //女生的标号 } sort(x,x+r,cmp); //边权从大到小排序 for(i=0;i<n+m;i++) makeset(i); for(i=0;i<r;i++) //最大生成树算法 if(find(x[i].a)!=find(x[i].b)) { cnt+=x[i].val; union2(x[i].a,x[i].b); } printf("%d\n",k*(m+n)-cnt); //输出答案 } return 0; }