您的位置:首页 > 产品设计 > UI/UE

poj 1679 The Unique MST 次小生成树算法

2013-08-09 13:27 148 查看
题目大意是判断一个图的最小生成树是否唯一

求出次小生成树,若次小生成树的权值不等于最小生成树,则唯一,若相等,则不唯一

#include <stdio.h>
#include <string.h>
int map[110][110],max[110][110],p[110],low[110],n,m,vis[110][110];
/*max[i][j]表示最小生成树中从i到j的路径中最长的边,map是边,p[i]是prim每次选进去的边一个节点(在之前选进去的集合中的节点)
vis[i][j]若为0,表示i到j无边,等于一表示有边但未选入最小生成树,等于2表示选入了最小生成树*/
int MAX(int a,int b)
{
if(a>b)
return a;
else return b;
}
int prim(int u)
{
int i,min,v,j,cost=0;
for(j=1;j<=n;j++)
{
low[j]=map[j][u];
p[j]=u;
}
low[u]=-1;
for(j=1;j<=n-1;j++)
{
min=50000;
for(i=1;i<=n;i++)
{
if(low[i]!=-1&&min>low[i])
{
min=low[i];
v=i;
}
}
low[v]=-1;
cost+=min;
vis[v][p[v]]=vis[p[v]][v]=2;/*在生成树中,所以改为2*/
for(i=1;i<=n;i++)
if(i!=v)
max[i][v]=max[v][i]=MAX(min,max[i][p[v]]);/*每次选入一个边都更新一遍max*/
for(i=1;i<=n;i++)
{
if(low[i]!=-1&&map[v][i]<low[i])
{
low[i]=map[v][i];
p[i]=v;
}
}
}
return cost;
}

int main()
{
int t,i,j,k,x,y,min,sum,w;
scanf("%d",&t);
for(i=0;i<t;i++)
{
min=50000;
scanf("%d%d",&n,&m);
memset(max,0,sizeof(max));/*刚开始时初始为0*/
memset(vis,0,sizeof(vis));
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
map[j][k]=50000;
for(j=0;j<m;j++)
{
scanf("%d%d%d",&x,&y,&w);
map[x][y]=map[y][x]=w;
vis[x][y]=vis[y][x]=1;
}
sum=prim(1);
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
if(vis[j][k]==1&&min>sum+map[j][k]-max[j][k])
/*将不在生成树中的边依次加入生成树,形成一个环,去掉环上原生成树中的最大边形成一棵较大的生成树*/
min=sum+map[j][k]-max[j][k];
if(min!=sum)
printf("%d\n",sum);
else
printf("Not Unique!\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: