题意:要征兵n个男兵和m个女兵,每个花费10000元,但是如果已经征募的男士兵中有和将要征募的女士兵关系好的,那么可以减少花费,给出关系,求最小花费。
解法:没有关系,需花费10000*(m+n)元,不断选取最大的关系值生成一颗最大生成树,再相减即可
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 #define r_max 50002 7 #define v_max 20002 8 int t; 9 int n, m ,r ; 10 11 struct Edge{ 12 int start, to, cost; 13 }; 14 Edge e[r_max]; 15 16 int cmp(const void *a, const void *b) { 17 Edge at = *(Edge *)a; 18 Edge bt = *(Edge *)b; 19 return bt.cost - at.cost; 20 } 21 int par[v_max]; 22 int rank[v_max]; 23 24 void init(int n) { 25 for(int i = 0; i <= n; i++) { 26 par[i] = i; 27 rank[i] = 0; 28 } 29 } 30 31 int find(int a) { 32 if(a == par[a]) { 33 return a; 34 } 35 else { 36 return par[a] = find(par[a]); 37 } 38 } 39 40 int main(int argc, char const *argv[]) 41 { 42 //freopen("input.txt","r",stdin); 43 scanf("%d",&t); 44 while(t--) { 45 scanf("%d %d %d",&n, &m, &r); 46 for(int i = 0; i < r; i++) { 47 scanf("%d %d %d",&e[i].start, &e[i].to, &e[i].cost); 48 e[i].to = e[i].to + n; 49 } 50 qsort(e, r, sizeof(Edge), cmp); 51 52 init(n+m); 53 int cut = 0; 54 for(int i = 0; i < r; i++) { 55 int a = find(e[i].start); 56 int b = find(e[i].to); 57 if(a == b) { 58 continue; 59 } 60 else { 61 if(rank[a] < rank[b]) { 62 par[a] = b; 63 } 64 else { 65 par[b] = a; 66 if(rank[a] == rank[b]) { 67 rank[a]++; 68 } 69 } 70 cut = cut + e[i].cost; 71 } 72 } 73 printf("%d ",10000*(n+m) - cut); 74 75 } 76 return 0; 77 }
也可以使用优先队列,不提倡,完全是练习
1 #include <cstdio> 2 #include <algorithm> 3 #include <vector> 4 #include <queue> 5 6 using namespace std; 7 #define r_max 50002 8 #define v_max 20002 9 int t; 10 int n, m ,r ; 11 12 struct Edge{ 13 int start, to, cost; 14 }; 15 16 int par[v_max]; 17 int rank[v_max]; 18 19 void init(int n) { 20 for(int i = 0; i <= n; i++) { 21 par[i] = i; 22 rank[i] = 0; 23 } 24 } 25 26 int find(int a) { 27 if(a == par[a]) { 28 return a; 29 } 30 else { 31 return par[a] = find(par[a]); 32 } 33 } 34 35 struct cmp{ 36 bool operator()(const Edge a,const Edge b){ 37 return a.cost < b.cost; 38 } 39 }; 40 priority_queue<Edge, vector<Edge>, cmp> que; 41 42 int main(int argc, char const *argv[]) 43 { 44 freopen("input.txt","r",stdin); 45 scanf("%d",&t); 46 while(t--) { 47 scanf("%d %d %d",&n, &m, &r); 48 for(int i = 0; i < r; i++) { 49 Edge e; 50 scanf("%d %d %d",&e.start, &e.to, &e.cost); 51 e.to = e.to + n; 52 que.push(e); 53 } 54 55 init(n+m); 56 int cut = 0; 57 while(!que.empty()) { 58 Edge e = que.top();que.pop(); 59 int a = e.start, b = e.to, c = e.cost; 60 printf("%d %d %d ",a,b,c); 61 a = find(a); 62 b = find(b); 63 if(a == b) { 64 continue; 65 } 66 else { 67 if(rank[a] < rank[b]) { 68 par[a] = b; 69 } 70 else { 71 par[b] = a; 72 if(rank[a] == rank[b]) { 73 rank[a]++; 74 } 75 } 76 cut = cut + c; 77 } 78 } 79 printf("%d ",10000*(n+m) - cut); 80 81 } 82 return 0; 83 }