题目链接:传送门Biubiubiu~~
分析:做的第一道最小生成树,用的的kruskal算法,算法原理很简单,大概就是将所有的边排序一下,一条条遍历,没在一个集合的就连在一起,在一个集合就跳过。基本就是模板题,稍微要处理下感觉就是把英文字母转换为数字。。算是自己的一个入门吧
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
int pre[95]; //并查集所需的父亲节点
int t;
void begin(){ //并查集初始化
for(int i=60;i<91;i++)
pre[i]=i;
}
int find(int z){ //查找合集的根源
int r=z;
while(pre[r]!=r)
r=pre[r];
return r;
}
void join(int x,int y){ //将两者加入一个集合中
int fx,fy;
fx=find(x);
fy=find(y);
if(fx!=fy)
pre[fx]=fy;
}
bool issame(int x,int y){ //判断两者是否在一个集合
return find(x)==find(y);
}
struct edge{ //存储点与点和它们之间的权值
int u,v,cost;
}es[80];
bool cmp(edge x,edge y){
return x.cost<y.cost;
}
int n;
int kruskal(){
sort(es,es+t,cmp); //从小到大排序
begin();
int res=0;
for(int i=0;i<t;i++){
edge e=es[i];
if(!issame(e.u,e.v)){ //判断是否加入
join(e.u,e.v);
res+=e.cost;
}
}
return res;
}
int main(){
while(cin>>n&&n){
t=0;
for(int i=0;i<n-1;i++){
char a,c; int b,d; //a是一行的第一个点,b是接下来的数量
cin>>a>>b;
for(int i=0;i<b;i++){
cin>>c>>d; //c是点,d是权值
es[t].u=(int)a;
es[t].v=(int)c;
es[t++].cost=d;
}
}
int total=kruskal();
cout<<total<<endl;
}
}