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

POJ-1679 The Unique MST 次小生成树

2013-01-31 12:45 597 查看
  题目链接:http://poj.org/problem?id=1679

  求是否存在多个最小生成树,其实就是求次小生成树的权值是否等于最小生成树。

  最小生成树的两个性质:

    1.切割性质:假定所有边权值不相等,设S为即非空集合也非全集V的子集,边e是满足一个端点在S内,另一个端点不在S内的所有边中权值最小的一个,则图G的所有生成树均包含e。

    2.回路性质:假定所有边权值不相等,设C是图G中的任意回路,边e是C上权值最大的边,则图G的所有生成树均不包含e。

  求次小生成树一遍朴素的做法就是枚举最小生成树中的边删去,然后再在图上求最小生成树,复杂度O(n*m*lgm);对于稀疏图来说,复杂度还是不高的。还有一种更好的方法,就是利用性质2。在最小生成树上家一条边u-v之后,图上会出现一条回路,因此删除的必须在最小生成树上u-v的路径上,而且是这条路径上的最长边。可以证明,次小生成树一定可以由最小生成树加一条边再删一条边得到(边交换)。因此只需求出”每对节点之间的最小瓶颈路“之后,然后依次枚举m条边就可以了。总复杂度O(n^2);

//STATUS:C++_AC_0MS_368KB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define LL __int64
#define pdi pair<double,int>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N=110,M=1000000,INF=0x3f3f3f3f,MOD=1999997;
const LL LLNF=0x3f3f3f3f3f3f3f3fLL;
const double DNF=100000000;

struct Edge{
int u,v,w;
}e[N*N];
int p
,vis
,mst

,d

,w

;
int T,n,m,mt;

int cmp(const Edge& a,const Edge& b)
{
return a.w<b.w;
}

int find(int x){return p[x]==x?x:p[x]=find(p[x]);}

int dfs(int& s,int u,int max)
{
int v;
for(v=1;v<=n;v++){
if(mst[u][v] && !vis[v]){
vis[v]=1;
d[s][v]=Max(max,w[u][v]);
dfs(s,v,d[s][v]);
}
}
return 0;
}

int Kruskal()
{
int i,j,x,y,sum=0;
for(i=1;i<=n;i++)p[i]=i;
sort(e,e+m,cmp);
mem(mst,0);
for(i=0;i<m;i++){
x=find(e[i].u);
y=find(e[i].v);
if(x!=y){
sum+=e[i].w;
p[y]=x;
mst[e[i].u][e[i].v]=mst[e[i].v][e[i].u]=1;
}
}
return sum;
}

int main()
{
//  freopen("in.txt","r",stdin);
int i,j,a,b,c,ok,ans;
scanf("%d",&T);
while(T--)
{
mt=0;
mem(w,-1);
scanf("%d%d",&n,&m);
for(i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
w[a][b]=w[b][a]=c;
e[i].u=a,e[i].v=b,e[i].w=c;
}

ans=Kruskal();
for(i=1;i<=n;i++){
mem(vis,0);vis[i]=1;
dfs(i,i,0);
}
for(i=0,ok=1;i<m;i++)
if(d[e[i].u][e[i].v]==e[i].w &&
!mst[e[i].u][e[i].v]){ok=0;break;}

if(ok)printf("%d\n",ans);
else printf("Not Unique!\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: