POJ 3723 Conscription
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10477 | Accepted: 3693 |
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 < 10000
Output
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
題意:須要征募女兵N人,男兵M人。每征募一個人須要花費10000美元,可是假設已經征募的人中有一些關系親熱的人,那麽能夠少花一些錢。給出若幹男女之間親熱關系,征募某個人的費用是10000 - (已經征募的人中和自己親熱度的最大值)。
要求通過適當的征募順序使得征募全部人所需費用最小。
思路:
把人看做頂點。關系看做邊,這個問題就轉化為求解無向圖中的最大權森林問題。
最大權森林問題能夠通過把全部邊權取反之後用最小生成樹的算法求解。
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 50000 + 10; struct edge { int u, v, cost; /* edge(int u, int v, int cost){ this -> u = u; this -> v = v; this -> cost = cost; }*/ }; bool comp(const edge& e1, const edge& e2) { return e1.cost < e2.cost; } edge es[maxn]; int N, M, R; int x[maxn], y[maxn], d[maxn]; int V, E; int par[maxn]; void init(int n) { for (int i = 0; i < n; i++){ par[i] = i; } } int find(int a) { if (par[a] == a) return a; else return par[a] = find(par[a]); } void unite(int a, int b) { a = find(a); b = find(b); if (a != b) par[a] = b; } bool same(int a, int b) { return find(a) == find(b); } int kruskal() { sort(es, es + E, comp); init(V); int res = 0; for (int i = 0; i < E; i++){ edge e = es[i]; if (!same(e.u, e.v)){ unite(e.u, e.v); res += e.cost; } } return res; } void solve() { V = N + M; E = R; for (int i = 0; i < R; i++){ es[i] = (edge){x[i], N + y[i], -d[i]}; } printf("%d\n", 10000 * (N + M) + kruskal()); } int main() { int t; scanf("%d", &t); while (t--){ scanf("%d%d%d", &N, &M, &R); for (int i = 0; i < R; i++){ scanf("%d%d%d", &x[i], &y[i], &d[i]); } solve(); } return 0; }
POJ 3723 Conscription