概述
2014-5-11更新
本题比较靠谱的解法是用次小生成树解。
具体思想可参考:http://blog.csdn.net/jarily/article/details/8912538
以下分析也转自上面的博客。代码按照自己的风格重写了。
基于 Kruscal 的写法可以参考 http://yzmduncan.iteye.com/blog/1018358
题目大意:
*给出一个连通无向图,判断它的最小生成树是否唯一;
*如果唯一,输出生成树的大小,否则输出"Not Unique!";
*
*算法思想:
*本题可以尝试求与最小生成树权值相等的树是否存在;
*但是更好的思路是直接求次小生成树,如果次小生成树等于最小生成树;
*则说明最小生成树不唯一,否则最小生成树一定是唯一的;
#include <cstdio>
#include <cstring>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int INF=0x3fffffff;
const int N=105;
int graph[N][N],dis[N];
int path[N][N];//从i到j的路径上最大边的权值
int pre[N]; //辅助数组,记录前驱
bool visit[N],used[N][N];//边是否在该MST中
int n,m;
int Prim ()
{
int Mst=0,i,j;
visit[1]=true;
for (i=1; i<=n; ++i)
{
dis[i]=graph[1][i];
pre[i]=1;
}
for (i=1;i<n;i++)
{
int k=-1;
for (j=1; j<=n; ++j)
if (visit[j]==false)
{
if (k==-1 || dis[j]<dis[k])
k=j;
}
used[k][pre[k]]=used[pre[k]][k]=true;//加入MST
Mst+=graph[pre[k]][k];
visit[k]=true;
for (j=1;j<=n;j++)
{
if (visit[j] && j!=k) //求从k到j的路径上最大边的权值
path[k][j]=path[j][k]=max(path[j][pre[k]],dis[k]);
if (visit[j]==false)
if (dis[j]>graph[k][j]) //更新相邻顶点的dis
{
dis[j]=graph[k][j];
pre[j]=k;
}
}
}
return Mst;
}
void Init ()
{
for (int i=0;i<=n;i++)
for (int j=i+1;j<=n;j++)
graph[i][j]=graph[j][i]=INF;
memset(visit,false,sizeof(visit));
memset(used,false,sizeof(used));
memset(path,0,sizeof(path));
}
int main ()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
Init();
int u,v,w,i;
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
graph[u][v]=graph[v][u]=w;
}
int Mst=Prim();
int ans=INF;
for (i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j && used[i][j]==false)
ans=min(ans,Mst+graph[i][j]-path[i][j]);
if (ans==Mst)
printf("Not Unique!n");
else
printf("%dn",Mst);
}
return 0;
}
2014-5-4 更新 这题测试数据貌似非常弱。。。当时用下面提到的方法居然水过去了,下面给一组反例:
1
4 5
1 2 2
1 3 2
1 4 2
2 4 101
3 4 101
正好最近准备学次小生成树,学会后换方法……
题目链接:http://poj.org/problem?id=1679
题意:给定的图是否具有唯一的最小生成树。
思路:看到网上的代码都是用次小生成树解的,但其实不用那么麻烦。
利用Prim算法求最小生成树,选择最小边时进行判断:是否有两个或以上的未选择顶点到已选顶点集合的权值相等的,若有则最小生成树不唯一。同时在松弛计算的时候也要
对刚加进的顶点进行权值是否相等的判断。
#include <cstdio>
#include <cstring>
const int INF=0x7fffffff;
int map[105][105],dis[105];
int m,n;
bool visit[105];
int Prim ()
{
int i,j,k;
int temp,ans=0;
for (i=1;i<=n;i++)
dis[i]=map[1][i];
visit[1]=true;
for (i=1;i<n;i++)
{
for (temp=INF,j=1;j<=n;j++)
if (dis[j]<temp && visit[j]==false)
temp=dis[k=j];
ans+=temp;
visit[k]=true;
for (j=1;j<=n;j++)
if (visit[j]==false && dis[j]==temp)
return -1;
for (j=1;j<=n;j++)
if (visit[j]==false)
if (dis[j]>map[k][j])
dis[j]=map[k][j];
else if (dis[j]==map[k][j] && dis[j]!=INF)
return -1;
}
return ans;
}
void init ()
{
int i;
for (i=1;i<=n;i++)
for (int j=1;j<=n;j++)
map[i][j]=INF;
for (i=1;i<=n;i++)
map[i][i]=0;
memset(visit,false,sizeof(visit));
}
int main ()
{
int T;
scanf("%d",&T);
while (T--)
{
int x,y,w;
scanf("%d%d",&n,&m);
init ();
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&w);
map[x][y]=w;
map[y][x]=w;
}
int ans=Prim();
if (ans == -1)
printf("Not Unique!n");
else
printf("%dn",ans);
}
return 0;
}
最后
以上就是追寻大炮为你收集整理的Poj 1679 The Unique MST (最小生成树唯一性判定)的全部内容,希望文章能够帮你解决Poj 1679 The Unique MST (最小生成树唯一性判定)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复