where
題意
- 最大花費總和
- 兩點要有一path
- 不會有cycle
思考
以 2. 和 3. 可以知道所要求的是一棵樹。
再來 1 是指路徑和最大,所以是 MST 。
Code
這裡是用 prim 。
#include <iostream>
#include <queue>
using namespace std;
int T, N, M, Q, arr[1005];
priority_queue<pair<int, pair<int, int> > > q;
void ini(void){
int a, b, c;
scanf("%d %d", &N, &M);
while(M--){
scanf("%d %d %d", &a, &b, &c);
q.push(make_pair(c, make_pair(a, b) ) );
}
}
//找頭頭
int par(int x){
if(arr[x] != x) return arr[x] = par(arr[x]);
else return x;
}
//這兩個是否同屬一個頭頭
bool check(int a, int b){
a = par(a);
b = par(b);
return (a != b);
}
void sol(void){
int c, i, j, ans = 0, conn = 0;
pair<int, int> p;
//初始化每個人的頭頭都是自己
for(int i = 1; i <= N; i++) arr[i] = i;
//conn 存已選邊的數量,用來檢查是否每點都有
while(!q.empty() && conn < N){
c = q.top().first;
p = q.top().second;
q.pop();
if(check(arr[p.first], arr[p.second])){
ans += c;
conn++;
//將這團的頭頭改為 p.first
//其實也可以只把這團的頭頭改掉就可了 :D
//arr[ par(p.second) ] = p.first;
i = p.second;
while(arr[i] != i){
j = arr[i];
arr[i] = p.first;
i = j;
}
arr[i] = p.first;
}
}
if(conn == N - 1) printf("%d\n", ans);
else printf("-1\n");
}
int main(void){
int i, j;
ini();
sol();
}
心得
~Union Find~Bomb~