某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。
输入格式说明:
输入的第1行给出村庄数目N (1<=N<=100);随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。
输出格式说明:
输出全省畅通需要的最低成本。
样例输入与输出:
序号 | 输入 | 输出 |
1 |
3 1 2 1 0 1 3 2 0 2 3 4 0 |
3 |
2 |
3 1 2 1 0 1 3 2 0 2 3 4 1 |
1 |
3 |
3 1 2 1 0 1 3 2 1 2 3 4 1 |
0 |
典型的最小生成树问题,刚开始用了普鲁姆算法,结果提示超时和段错误。超时好理解,段错误真的不知道为什么。
贴一下代码:
#include<iostream> #include<stdio.h> #include<algorithm> using namespace std; int a[101][102]={0}; int visit[102]={0}; int p[102]={0}; int n=0; #define inf 0x3f3f3f3f int prime() { int min=0; int sum=0; int cnt=0; int j=0,i=0,k=0; for(i=0;i<n;i++) { min=inf; for(j=2;j<=n;j++)//在候选边里面找一条最小的 { if((visit[j]!=1)&&p[j]<min) { min=p[j]; cnt=j; } } if(min!=inf) { sum+=min; visit[cnt]=1;//已经访问过了 for(k=2;k<=n;k++)//更新权值 { if((visit[k]!=1)&&(p[k]>a[cnt][k])) { p[k]=a[cnt][k]; } } } } return sum; } int main() { int N=0; int i=0,j=0,flag=0,d=0; memset(a,inf,sizeof(a)); scanf("%d",&N); N=N*(N-1)/2; n=N; while(N--){ scanf("%d%d%d%d",&i,&j,&d,&flag); a[i][j]=d; if(flag==0) { a[j][i]=a[i][j]; }else { a[j][i]=0; a[i][j]=0; } } for(i=1;i<=n;i++) { p[i]=a[1][i]; } visit[1]=1;//取1号点为生成树 int ans=0; ans=prime();//普鲁姆算法 取点 printf("%d\n",ans); return 0; }
后来在网上找到了答案,发现他的代码也是普鲁姆算法,只不过有一些不一样。为了缩短时间和内存,他做了一点改进省略了这一段:
for(i=1;i<=n;i++) { p[i]=a[1][i]; }
直接利用那个a[][]这个数组,感觉也没差多少,因为这段的时间复杂度也就O(n)和本身整体的复杂度O(n^2)相比应该是可以忽略的。后来又仔细看了一下题目时间限制:10MS,比一般的题目都要少很多,一般题目有400MS。所以这也可能是一个因素把。至于段错误真不知道错哪里了,有知道的希望可以告知,不胜感激。
附网上的答案:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define inf 0x3f3f3f3f int map[100][100]; int s[100],vis[100]; int n,m; int prim() { int i,j,t,p,min,cnt,minpos; int ans=0; cnt=0; vis[1]=1; s[cnt++]=1; while(cnt<n) { t=cnt; min=inf; for(i=0;i<t;i++) { p=s[i]; for(j=1;j<=n;j++) { if(!vis[j]&&map[p][j]<min) { min=map[p][j]; minpos=j; } } } ans+=min; s[cnt++]=minpos; vis[minpos]=1; } return ans; } int main() { int i,sum; while(~scanf("%d",&n)&&n) { memset(vis,0,sizeof(vis)); memset(map,inf,sizeof(map)); int b,c,d,sta; m=n*(n-1)/2; for(i=0;i<m;i++) { scanf("%d%d%d%d",&b,&c,&d,&sta); if(sta==0) map[b][c]=map[c][b]=d; else map[b][c]=map[c][b]=0; } sum=prim(); printf("%d\n",sum); } return 0; }
原文:http://blog.csdn.net/linsheng9731/article/details/22760905