题目大意:自己看
分析:最后答案就是10000*(n+m)-所有人加进来能获得的最大权值和,把权值取负就是求最小生成树了,节点编号是从0开始的- -
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm> 6 #include <map> 7 #include <queue> 8 #include<vector> 9 #define maxn 20010 10 #define maxm 50010 11 #define INF 0x3fffffff 12 using namespace std; 13 struct edge{ 14 int u,v,cost; 15 edge(){} 16 edge(int _u,int _v,int _cost){ 17 u=_u;v=_v;cost=_cost; 18 } 19 }; 20 bool cmp(edge a,edge b){ 21 return a.cost<b.cost; 22 } 23 int V,E; 24 int father[maxn]; 25 void init(){ 26 for(int i=0;i<=V;++i){ 27 father[i]=i; 28 } 29 } 30 int Find(int x){ 31 return father[x]==x?x:father[x]=Find(father[x]); 32 } 33 void Union(int x,int y){ 34 x = Find(x); 35 y = Find(y); 36 if(x!=y)father[x]=y; 37 } 38 bool same(int x,int y){ 39 return Find(x)==Find(y); 40 } 41 edge G[maxm]; 42 int cnt=0; 43 void addedge(int u,int v,int cost){ 44 G[cnt++]=edge(u,v,cost); 45 } 46 int kruskal(){ 47 sort(G,G+cnt,cmp); 48 init(); 49 int ans=0; 50 for(int i=0;i<cnt;++i){ 51 edge e = G[i]; 52 if(!same(e.u,e.v)){ 53 Union(e.u,e.v); 54 ans+=e.cost; 55 } 56 } 57 return ans; 58 } 59 int n,m,R; 60 int main (){ 61 int t; 62 scanf("%d",&t); 63 while(t--){ 64 scanf("%d%d%d",&n,&m,&R); 65 cnt=0; 66 V=n+m; 67 for(int i=0;i<R;++i){ 68 int u,v,w; 69 scanf("%d%d%d",&u,&v,&w); 70 addedge(u,v+n,-w); 71 } 72 printf("%d\n",(n+m)*10000+kruskal()); 73 } 74 }