Descriptionsios
須要徵募女兵N人,男兵M人。 每招募一我的須要花費10000美圓。 若是已經招募的人中有一些關係親密的人,那麼能夠少花一些錢。 給出若干男女以前的1 ~ 9999 之間的親密度關係, 招募某我的的費用是 10000 - (已經招募了的人中和本身的親密度的最大值)。 要求經過適當的招募順序使得招募全部人所花費的費用最小。算法
Input測試
輸入N, M, R;
接下來輸入R行 (x, y, d) 表示第 x 號男兵和第 y 號女兵之間的親密度是 dspa
Output.net
輸入最小花費的值。code
Sample Inputblog
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 781ip5 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 3133ci
Sample Output
71071
54223
題目連接
https://vjudge.net/problem/POJ-3723
把人當作點,關係看做邊,轉化爲求解無向圖的最大權森林問題,這個問題又能夠經過把全部邊取反以後用最小生成樹的算法求解
典型的kruskal算法
注意要用scanf printf
AC代碼
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define IOS \ ios_base::sync_with_stdio(0); \ cin.tie(0); #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x, y) memset(x, y, sizeof(x)) #define Maxn 1000000 + 10 using namespace std; int N, M, R; int x[Maxn], y[Maxn], d[Maxn];//男孩 女孩 關係度 struct edge { int u, v, cost;//u到v的距離爲cost }; bool cmp(const edge &e1, const edge &e2)//從小到大排序 { return e1.cost < e2.cost; } edge es[Maxn]; int par[Maxn]; void init(int n)//初始化並查集 { for (int i = 0; i <= n; i++) par[i] = i; } int findr(int x)//尋根 { if (par[x] == x) return x; return par[x] = findr(par[x]); } void unite(int x, int y)//合併 { x = findr(x); y = findr(y); if (x == y) return; par[x] = y; } bool same(int x, int y)//判斷根是否相同 { return findr(x) == findr(y); } int kruskal(int V, int E)//kruskal算法求最小生成樹 { sort(es, es + E, cmp); 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; } int main() { int T; scanf("%d", &T); while (T--)//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]); int V, E; V = N + M;//頂點個數 E = R;//邊個數 for (int i = 0; i < E; i++)//存入結構體 { es[i] = (edge){ x[i], N + y[i], -d[i]}; } printf("%d\n", 10000 * (N + M) + kruskal(V, E)); } return 0; }