poj1251 - Jungle Roads

来源:互联网 发布:做淘宝刷手的接单技巧 编辑:程序博客网 时间:2024/04/18 09:04

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

 

/*primMemory 168KTime    0MS*/#include <iostream>using namespace std;#define MAXV 30#define inf 1<<29int 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;elsemap[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;}


 

=======================================================================

 

/*kruskalMemory 172KTime    0MS*/#include <iostream>using namespace std;#define MAXM 900#define MAXV 30typedef 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;}