这道题大致的意思是一个部落有n个村子,若干条道路,每个道路有它的花费,要修一条可以连接所有村子的路,保证花费最小,典型的最小生成树。样例如下:
样例第一行是n个村子,之后的n-1行是道路信息
A 2 B 12 I 25
代表有两条路通往村子A,AB之间的花费是12,AI之间的花费是25。
所以可以使用Kruskal算法的思想,利用并查集解决:
#include<iostream>
#include<queue>
using namespace std;
const int N = 30;
struct Edges{
int n1, n2, len;
Edges(int n1, int n2, int l): n1(n1), n2(n2), len(l){}
bool operator>(const Edges e) const{
return len > e.len;
}
};
int arr[N];
void Initial(int *arr, int n){
for(int i = 0; i < n; i++) arr[i] = -1;
}
int Find(int *arr, int x){
int root = x;
while(arr[root] >= 0) root = arr[root];
while(x != root){
int t = arr[x];
arr[x] = root;
x = t;
}
return root;
}
bool Union(int *arr, int x, int y){
if(x == y) return false;
int root1 = Find(arr, x);
int root2 = Find(arr, y);
if(root1 != root2){
if(arr[root2] > arr[root1]){
arr[root1] += arr[root2];
arr[root2] = root1;
}else{
arr[root2] += arr[root1];
arr[root1] = root2;
}
return true;
}
return false;
}
int main(){
int n, k, dis;
char ch1, ch2;
while(cin>>n){
if(n == 0) break;
Initial(arr, n);
priority_queue<Edges, vector<Edges>, greater<Edges>> pq;
for(int i = 0; i < n - 1; i++){
cin>>ch1>>k;
if(k){
for(int j = 0; j < k; j++){
cin>>ch2>>dis;
pq.push(Edges(ch1 - 'A', ch2 - 'A', dis));
}
}
}
int sum = 0, edges = 0;
while(!pq.empty()){
Edges e = pq.top();
pq.pop();
if(Union(arr, e.n1, e.n2)){
sum += e.len;
if(++edges == n - 1) break;
}
}
printf("%d\n", sum);
}
return 0;
}