POJ_1679 最小生成树是否唯一

http://poj.org/problem?id=1679

/* <1>要求:这道题的要求是给定一个无向联通图,判断这个图的最小生成树MST是不是唯一的,如果是唯一的则 打印出最小值,如果不是唯一的给出提示 <2>分析:采用Kruskal算法来计算最小生成树,仔细分析其过程不难发现这个图的MST不唯一的充分必要条件是 在Kruskal运算过程中如果选中的当前边a构成了环,且在所有包含这条边的环中如果存在和这条边权值相等的 边b,则MST不唯一,因为总是可以利用a取代b构成一个新的MST.算法清楚了, 那么实现最难的地方就是找环了 <3>实现:为了提高计算的速度,我将边保存两份,一份用结构表示,存储所有边,用来排序和MST遍历边用; 另外一份用邻接表表示有提高计算环时候的处理速度,数据结构确定了那么很容易利用DFS回溯,在DFS回溯的 过程中判断环以及是否有和目标边权值相等的边,判断环没有用并查集而是直接在DFS中判断*/ #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; #define MAX 250 #define INF 1000000 int t,n,m; int result; struct node { int v1;int v2;int len; }e[MAX]; int dis[MAX][MAX]; void init()//初始化 { for(int i=0;i<n;i++) for(int j=0;j<n;j++) dis[i][j]=INF; } int prim() { int result=0; int i,j,min,minL,vx,vy,leng; for(i=0;i<n-1;i++) { e[i].v1=0; e[i].v2=i+1; e[i].len=dis[0][i+1]; } for(i=0;i<n-1;i++) { minL=INF; min=-1; for(j=i;j<n-1;j++) //找出最小边 { if(e[j].len<minL) { minL=e[j].len; min=j; } } if(min==-1) break; swap(e[min],e[i]); result+=minL; for(j=0;j<i;j++)//在prim模板的基础上加上这个循环判断mst是否唯一 { if(dis[e[j].v2][e[i].v2]==minL && e[j].v2!=e[i].v1) return -1; } vx=e[i].v2; for(j=i+1;j<n-1;j++) { vy=e[j].v2; leng=dis[vx][vy]; if(leng<e[j].len) { e[j].len=leng; e[j].v1=vx; } } } return result; } int main() { // freopen("in.txt","r",stdin); while(scanf("%d",&t)!=EOF) { int x,y,z; for(int i=0;i<t;i++) { scanf("%d%d",&n,&m); init(); for(int j=0;j<m;j++) { scanf("%d%d%d",&x,&y,&z); x--; y--; dis[x][y]=dis[y][x]=z; } result=prim(); if(result<0) printf("Not Unique!/n"); else printf("%d/n",result); } } return 0; }   

你可能感兴趣的:(POJ_1679 最小生成树是否唯一)