题目链接在这里
题目大意:
村与村之间有道路相互连通,维护道路的费用太高了,因此村里的长老决定只维护其中的一部分,并且这维护的部分仍能使村之间连通。求维护的最小成本是多少。
思路分析:
很容易想到这是求最小生成树的问题,只是对输入的处理可能有一丢丢麻烦。搞定输入之后,把最小生成树莽出来就行了。
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define rep(i, x) for(int i = 0; i < x; ++i)
#define clr(x) memset(x, 0, sizeof(x))
using namespace std;
const int MaxN = 105;
struct Edge{
int x, y, val;
bool operator < (const Edge& e) const{
return val > e.val;
}
};
int n;
int par[MaxN], r[MaxN];
priority_queue<Edge> que;
void init(){
clr(r);
rep(i, MaxN) par[i] = i;
}
int Find(int x){
if(x == par[x]) return x;
return par[x] = Find(par[x]);
}
void unite(int x, int y){
x = Find(x);
y = Find(y);
if(x == y) return;
if(r[x] < r[y]) par[x] = y;
else{
par[y] = x;
if(r[x] == r[y]) ++r[x];
}
}
bool check(int x, int y){
return Find(x) == Find(y);
}
int kruskal(){
init();
int ans = 0;
while(!que.empty()){
Edge e = que.top();
que.pop();
if(check(e.x, e.y)) continue;
ans += e.val;
unite(e.x, e.y);
}
return ans;
}
int main(){
char str[100];
while(scanf("%d", &n), n){
gets(str);
//int m = (n - 1) * n / 2;
int t;
int x, y, val;
rep(i, n - 1){
scanf(" %s %d", str, &t);
x = str[0] - 'A';
rep(j, t){
scanf(" %s %d", str, &val);
y = str[0] - 'A';
//printf("x:%d, y:%d, val:%d\n", x, y, val);
que.push(Edge{x, y, val});
}
}
printf("%d\n", kruskal());
}
return 0;
}