您的位置:首页 > 其它

POJ_1679 最小生成树是否唯一

2010-10-26 19:06 316 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: