想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:首先给你一个图,需要你求出最小生成树,输入N个节点,用大写字母表示了节点,然后节点与节点之间有权值。
比如有9个节点,然后接下来有n-1行表示了边的情况,拿第一行举例
A 2 B 12 I 25
表示A有两个邻点,B和I,AB权值是12,AI权值是25
解题思路:一个很直接的模板题,分别用prim和kruskal实现
/*
prim
Memory 168K
Time 0MS
*/
#include <iostream>
using namespace std;
#define MAXV 30
#define inf 1<<29
int map[MAXV][MAXV],n,d[MAXV],vis[MAXV];
void prim(){
int i,j,mi,v;
for(i=0;i<n;i++){
d[i]=map[0][i];
vis[i]=0;
}
for(i=1;i<=n;i++){
mi=inf;
for(j=0;j<n;j++){
if(!vis[j] && mi>d[j]){
v=j;
mi=d[j];
}
}
vis[v]=1;
for(j=0;j<n;j++)
if(!vis[j] && d[j]>map[v][j]) //和dijstra不同的一点是这里找的是最小邻边
d[j]=map[v][j];
}
for(i=1;i<n;i++) d[0]+=d[i];
printf("%d\n",d[0]);
}
int main(){
int i,j,m,c;
char a[2],b[2];
while(scanf("%d",&n) && n){
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==j)
map[i][j]=0;
else
map[i][j]=inf;
for(i=1;i<n;i++){
scanf("%s%d ",&a,&m);
for(j=0;j<m;j++){
scanf("%s%d ",&b,&c);
map[a[0]-'A'][b[0]-'A']=map[b[0]-'A'][a[0]-'A']=c;
}
}
prim();
}
return 0;
}
=======================================================================
/*
kruskal
Memory 172K
Time 0MS
*/
#include <iostream>
using namespace std;
#define MAXM 900
#define MAXV 30
typedef struct{
int s,t,w;
}Edge;
int n,esum,set[MAXV];
Edge edge[MAXM];
int find(int x){
int rt;
if(set[x]!=x){
rt=find(set[x]);
set[x]=rt;
return set[x];
}else return x;
}
bool Union(int a,int b){
int fa,fb;
fa=find(a); //这里用并查集来判断是否有环
fb=find(b);
if(fa==fb) return 0; //构成环了,这条边不能加进来
set[fa]=fb;
return 1;
}
void kruskal(){
int i,ans=0;
for(i=0;i<esum;i++){
if(Union(edge[i].s,edge[i].t)){
//如果将这条边加进来构成不了环就加进来
//还可以加一个计数,加到n-1就退出循环,如果不足n-1就构成不了生成树
ans+=edge[i].w;
}
}
printf("%d\n",ans);
}
int cmp(const void * a,const void *b){
return (*(Edge*)a).w-(*(Edge*)b).w;
}
int main(){
int i,j,m,c;
char a[2],b[2];
while(scanf("%d",&n) && n){
esum=0;
for(i=0;i<=n;i++) set[i]=i;
for(i=1;i<n;i++){
scanf("%s%d ",&a,&m);
for(j=0;j<m;j++){
scanf("%s%d ",&b,&c);
edge[esum].s=a[0]-'A';
edge[esum].t=b[0]-'A';
edge[esum++].w=c;
}
}
qsort(edge,esum,sizeof(edge[0]),cmp); //首先对所有边的权值从小到大排序
kruskal();
}
return 0;
}