Conscription(POJ 3723)
阿新 • • 發佈:2018-08-12
矛盾 The true 求解 have const fine i++ when
- 原題如下:
Conscription
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16584 Accepted: 5764 Description
Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girl x
Input
The first line of input is the number of test case.
The first line of each test case contains three integers, N, M and R.
Then R lines followed, each contains three integers xi, yi and di.
There is a blank line before each test case.1 ≤ N, M ≤ 10000
0 ≤ R ≤ 50,000
0 ≤ xi < N
0 ≤ yi < M
0 < di < 10000Output
For each test case output the answer in a single line.Sample Input
2 5 5 8 4 3 6831 1 3 4583 0 0 6592 0 1 3063 3 3 4975 1 3 2049 4 2 2104 2 2 781 5 5 10 2 4 9820 3 2 6236 3 1 8864 2 4 8326 2 0 5156 2 0 1463 4 1 2439 0 4 4373 3 4 8889 2 4 3133
Sample Output
71071 54223
- 題解:設想這樣一個無向圖:在征募某個人a時,如果使用了a和b之間的關系,那麽就連一條a到b的邊,假設這個圖中存在圈,那麽無論以什麽順序征募這個圈上的所有人,都會產生矛盾,即由於圈的存在,矛盾是必然的,由此可以知道,這個圖應該是一片森林。反過來,給定一片森林裏,必然可以使用對應的關系確定征募的順序。綜上,把人看作點,關系看作邊,這個問題就可以轉化為求解無向圖中的最大權森林問題,最大權森林問題可以通過把所有邊權取反後用最小生成樹的算法求解
- 代碼:
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <algorithm> 5 #include <cctype> 6 #define num s-‘0‘ 7 8 using namespace std; 9 10 struct edge 11 { 12 int u; 13 int v; 14 int cost; 15 }; 16 17 const int MAX_V=30000; 18 const int MAX_E=60000; 19 const int INF=0x3f3f3f3f; 20 int K,N, M, E, V; 21 edge es[MAX_E]; 22 long long res; 23 int par[MAX_V]; 24 int r[MAX_V]; 25 26 void kruskal(); 27 void init(); 28 int find(int); 29 void unite(int, int); 30 bool same(int, int); 31 32 void read(int &x){ 33 char s; 34 x=0; 35 bool flag=0; 36 while(!isdigit(s=getchar())) 37 (s==‘-‘)&&(flag=true); 38 for(x=num;isdigit(s=getchar());x=x*10+num); 39 (flag)&&(x=-x); 40 } 41 42 void write(int x) 43 { 44 if(x<0) 45 { 46 putchar(‘-‘); 47 x=-x; 48 } 49 if(x>9) 50 write(x/10); 51 putchar(x%10+‘0‘); 52 } 53 54 bool compare(const edge &e1, const edge &e2) 55 { 56 return e1.cost<e2.cost; 57 } 58 59 int main() 60 { 61 read(K); 62 for (int j=0; j<K; j++) 63 { 64 res=0; 65 read(N);read(M);read(E);V=N+M; 66 for (int i=0; i<E; i++) 67 { 68 read(es[i].u);read(es[i].v);read(es[i].cost); 69 es[i].v+=N;es[i].cost=-es[i].cost; 70 } 71 kruskal(); 72 write(10000*(N+M)+res); 73 putchar(‘\n‘); 74 } 75 } 76 77 void init() 78 { 79 for (int i=0; i<V; i++) 80 { 81 par[i]=i; 82 r[i]=0; 83 } 84 } 85 86 int find(int x) 87 { 88 if (par[x]==x) return x; 89 return par[x]=find(par[x]); 90 } 91 92 void unite(int x, int y) 93 { 94 x=find(x); 95 y=find(y); 96 if (x==y) return; 97 if (r[x]<r[y]) par[x]=y; 98 else 99 { 100 par[y]=x; 101 if (r[x]==r[y]) r[x]++; 102 } 103 } 104 105 bool same(int x, int y) 106 { 107 return (find(x)==find(y)); 108 } 109 110 void kruskal() 111 { 112 sort(es, es+E, compare); 113 init(); 114 for (int i=0; i<E; i++) 115 { 116 edge e=es[i]; 117 if (!same(e.u, e.v)) 118 { 119 unite(e.u, e.v); 120 res+=e.cost; 121 } 122 } 123 }
Conscription(POJ 3723)