poj3723 最大权森林

3723

题目大意:自己看

分析:最后答案就是10000*(n+m)-所有人加进来能获得的最大权值和,把权值取负就是求最小生成树了,节点编号是从0开始的- -

 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+m)*10000+kruskal());
73     }
74 }
View Code
原文地址:https://www.cnblogs.com/shuzy/p/3783158.html