想看更多的解题报告: 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; }