题意:
这个题目很长,很长。。。。。
就是有一些村庄,他们之间的路要重新修缮,他们想要花费最少的钱来修,并且要使所有的村庄保持道路,不修就不会有这些路了。
分析
最小生成树问题,我现在只会一个Kruskal,克鲁斯卡尔算法。
算是板子题吧,注释有解释
代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <iomanip>
#define maxn 100
#define ll long long
#define debug cout<<"***********"<<endl;
using namespace std;
struct Edge{ //结点结构体
int u,v,w;
Edge(){}
Edge(int u,int v,int w){//构造方法
this->u = u;
this->v = v;
this->w = w;
}
bool operator < (const Edge &a){//排序规则
return w < a.w;
}
};
char a,b;
Edge e[maxn];
int pa[90];
void init(){//并查集初始化
for(int i = 0; i <= 30; i++){
pa[i] = i;
}
}
int findset(int x){//寻找集合代表并进行路径压缩
return x == pa[x] ? x : pa[x] = findset(pa[x]);
}
int main(){
std::ios::sync_with_stdio(false);
int n,m,x,w;
while(cin>>n && n){
m = 0;
int cnt = n;
n--;
while(n--){
cin>>a>>x;
int u = a - 'A' + 1;
while(x--){
cin>>b>>w;
int v = b - 'A' + 1;
e[m++] = Edge(u,v,w);//添加边,并记录边的个数。
}
}
sort(e,e+m);
int cost = 0;//花费
init();
for(int i = 0; i < m; i++){//贪心,每次找最小花费的边,如果是不同树中的,添加到最小生成树中
Edge u = e[i];
int x = u.u;
int y = u.v;
x = findset(x);
y = findset(y);
if(x != y){
cost += u.w;
pa[x] = y;
cnt--;
}
if(cnt == 1){
break;
}
}
cout<<cost<<endl;
}
return 0;
}