地址 https://www.papamelon.com/problem/245
需要徵募女兵 N 人,男兵 M 人。
每徵募一個人需要花費 10000 人民幣。如果兩個人之間有某種關係,則可以少花錢。
例如,一男一女之間的關係值爲 d,其中一人已經被徵募,當我們再徵募第二個人時,花費爲 10000−d 元。
多人之間可以形成環狀關係,來看一個例子:
A 和 B 有關係,可減免 100 元
B 和 C 有關係,可減免 200 元
C 和 A 有關係,可減免 300 元
招募 A 花費 10000 元
招募 B,因爲有 A,減免 100 元,花費 10000−100 元
招募 C,因爲有 B,減免
200 元,花費 10000−200 元
儘管 C 和 A 之間有關係,但 A,B,C 都招進來了,無法再減免,總花費是
30000−300 元
以上只是一種招人方案,並不一定是最省錢的
現在給出所有的關係信息,讓我們徵募到
N 女 M 男,求最小花費。
輸入
第一行整數 T(1≤T≤10),表示有多少組測試數據
每組測試數據最開始先是一個空行,再接着以下的部分:
第一行有 3 個整數
N 和 M 和 R
接下來的 R 行,每行均表示一條人際關係,三個整數
x,y,d, 表示女兵 x 和男兵 y 的關係值爲 d
1≤N,M≤10000
1≤R≤50000
0<d<10000
0≤x<N
0≤y<M
輸出T 行,每行一個整數,表示該組測試數據中所需的最小費用
樣例 1
輸入
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
輸出
71071
54223
解答
#include <iostream>
#include <algorithm>
#include <memory.h>
using namespace std;
const int N = 200010, M = 500010;
struct Edge {
int a, b, w;
bool operator<(const Edge& e) {
return w > e.w;
}
}edges[M];
int f[N];
int t, m, n, r;
int find(int x) {
if (f[x] != x) f[x] = find(f[x]);
return f[x];
}
int kruskal() {
sort(edges, edges + r);
cout <<edges[0].w <<" "<<edges[1].w<<endl;
for (int i = 0; i <= m + n; i++) f[i] = i;
int res = 0;
for (int i = 0; i < r; i++) {
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a); b = find(b);
if (a != b) {
f[a] = b;
res += w;
}
}
return res;
}
int main() {
cin >> t;
while (t--) {
cin >> n >> m >> r;
memset(edges, 0, sizeof edges);
for (int i = 0; i < r; i++) {
int a, b, w; cin >> a >> b >> w;
edges[i].a = a; edges[i].b = b+n; edges[i].w = w;
}
int t = kruskal();
cout << 10000 * (m + n) - t << endl;
}
return 0;
}