POJ3723最小生成树

题意:从一个起点出发连接男孩子和女孩子,若是两者之间有连接的,则花费为10000-d,若是没有连接的则花费为10000

分析:很显然是一个最小生成树,但是我们希望的是d越大越好,因为d越大,10000-d就越小。因此我们在此处用-d来作为最小生成树边的权值,这样就能得出如何连接才能使花费最少了

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <bitset>
10 #include <cmath>
11 #include <queue>
12 #include <stack>
13 using namespace std;
14 const int maxn=50010;
15 int n,m,r;
16 struct edge{
17     int u,v,cost;
18 };
19 bool cmp(const edge& e1,const edge& e2){
20     return e1.cost<e2.cost;
21 }
22 edge es[maxn];
23 
24 //并查集部分
25 int par[maxn];
26 int rankl[maxn];
27 void init(int n){
28     for(int i=0;i<=n;i++){
29         par[i]=i;
30         rankl[i]=0;
31     }
32 }
33 int findl(int x){
34     if(par[x]==x)
35         return x;
36     else{
37         return par[x]=findl(par[x]);
38     }
39 }
40 void unite(int x,int y){
41     x=findl(x);
42     y=findl(y);
43     if(x==y)  return;
44     if(rankl[x]<rankl[y]){
45         par[x]=y;
46     }else{
47         par[y]=x;
48         if(rankl[x]==rankl[y])  rankl[x]++;
49     }
50 }
51 bool same(int x,int y){
52     return findl(x)==findl(y);
53 }
54 
55 //最小生成树
56 int kruskal(){
57     sort(es,es+r,cmp);
58     init(n+m);
59     int res=0;
60     for(int i=0;i<r;i++){
61         edge e=es[i];
62         if(!same(e.u,e.v)){
63             unite(e.u,e.v);
64             res+=e.cost;
65         }
66     }
67     return res;
68 }
69 int main()
70 {
71     int t;
72     cin>>t;
73     while(t--)
74     {
75         scanf("%d%d%d",&n,&m,&r);
76         for(int i=0;i<r;i++){
77             int x,y,d;
78             scanf("%d%d%d",&x,&y,&d);
79             es[i].u=x,es[i].v=y+n,es[i].cost=-d;
80         }
81         printf("%d
",10000*(n+m)+kruskal());
82     }
83     return 0;
84 }
View Code
原文地址:https://www.cnblogs.com/wolf940509/p/5669326.html