ZOJ 1542 Network

来源:互联网 发布:用友网络股票 编辑:程序博客网 时间:2024/05/29 07:51

ZOJ 1542 Network

      严重怀疑ZOJ是想通过这道题的错误样例让所有做它的学生加深深深深对最小生成树的理解。

      题意:给出一个图的顶点的数目、弧的数目、顶点间的连通信息、边的权值。求最小生成树,要求打印出这颗最小生成树的最大边的权值、边的数目,每条边的两个顶点的编号。

      首先、不论用什么算法来做,当存在权值相同的边的时候,虽然得出的最小生成树可能不唯一,但是得出的最小生成树所出现的权值的种类和每一类权值出现的次数是一样的。因、为、最小生成树的边的数目是固定的。

      这也是题目的一个奇葩之处,竟然让算最小生成树的边的数目,不是必然是 顶点的数目-1 吗……

      此外,题目给出样例还有两个错误,一是最小生成树的路径不对;二是,样例貌似使用克鲁斯卡尔算法来做的,所以顶点的编号是按照边的权值升序和顶点编号的前后顺序打印的。

      好吧,除了题目的样例再拿一个课本上的图做样例。

      数据结构(C语言版) P174 图。

      样例:

      输入:

           6 10

           1 2 6

           1 3 1

           1 4 5

           2 3 5

           2 5 3

           3 4 5

           3 5 6

           3 6 4

           4 6 2

           5 6 6

     输出:

           5

           5

           1 3

           3 6

           6 4

           3 2

           2 5

    细节+代码如下:

   

#include<stdio.h>int edge[1500][1500]; /*全局。本来写成图的结构体,动态变量不能开这么大。*/int n,e;int createudg(int edge[1500][1500],int n,int e){int i,a,b,value,j;for(i = 0;i<=1100;i++){for(j = 0;j<=1100;j++)edge[i][j] = 100000000; /*初始化,Debug发现忘写了。*/}for(i = 1;i<=e;i++){scanf("%d%d%d",&a,&b,&value);edge[a-1][b-1] = edge[b-1][a-1] = value;}return 0;}int prim(int edge[1500][1500],int n){ /*普利姆算法。*/int i,dis[1100],visit[1100],k,min,j,index,a[1100],b[1100],g[1100],m[1100],t,max;for(i = 0;i<=11;i++){dis[i] = 100000000;visit[i] = 0;}dis[0] = 0;k = 0;t = 0;max = 0;for(i = 0;i<=n-1;i++){min = 100000000;for(j = 0;j<=n-1;j++){if(visit[j]==0&&dis[j]<min){index = j;min = dis[j];}}visit[index] = 1;if(j!=0&&dis[index]>max)max = dis[index];if(index!=0){g[t] = b[index];m[t] = a[index];t++;}for(j = 0;j<=n-1;j++){if(visit[j]==0&&edge[index][j]<dis[j]){dis[j] = edge[j][index];a[j] = j+1; /*记住两端的顶点。*/b[j] = index+1;}}}printf("%d\n",max);printf("%d\n",n-1);for(i = 0;i<=t-1;i++)printf("%d %d\n",g[i],m[i]);return 0;}int main(){while(scanf("%d%d",&n,&e)!=EOF){createudg(edge,n,e);prim(edge,n);}return 0;}


 

原创粉丝点击