POJ 1679 The Unique MST

来源:互联网 发布:matlab编程实例并解析 编辑:程序博客网 时间:2024/06/11 13:14

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

题目大意:

给你一些点,判断MST(最小生成树)是否唯一。



--------------------------------------------------------此题已更新最新题解报告--------------------------------------------------------

http://blog.csdn.net/murmured/article/details/18868481

思路:

首先先建立MST,然后把这个MST的边一个个尝试不使用,构建另外一颗MST,然后判断权值是否相等。

这样复杂度需要O(n^3)。。


还可以用次最小生成树的方法解决。

#include<cstdio>#include<algorithm>using namespace std;const int MAXN=101;int fa[MAXN];struct point{int x,y;int len;}data[MAXN*MAXN],pre[MAXN*MAXN]; //pre 记录等一下用到了哪些条边bool operator < (const point &a ,const point &b) //sort 重载比较函数{return a.len<b.len;}void UFinit(int n)     //并查集初始化{for(int i=1;i<=n;i++)fa[i]=i;}int find(int cur)      //带路径压缩的并查集查询函数,简洁而优雅~{return fa[cur]==cur? cur : fa[cur]=find(fa[cur]);}int kruskal(int n,int m,int &prelen){UFinit(n);int ans=0;for(int i=0;i<m;i++){int rootx=find(data[i].x);int rooty=find(data[i].y);if(rootx!=rooty){fa[rootx]=rooty;ans+=data[i].len;pre[prelen++]=data[i];}}return ans;}int kruskal2(int n,int m,int nox,int noy)//nox noy 代表直接连接这两个点之间的边不选{UFinit(n);int ans=0;for(int i=0;i<m;i++){if(data[i].x==nox && data[i].y==noy)continue;int rootx=find(data[i].x);int rooty=find(data[i].y);if(rootx!=rooty){fa[rootx]=rooty;ans+=data[i].len;}}return ans;}int main(){int T;scanf("%d",&T);while(T--){int n,m;scanf("%d%d",&n,&m);for(int i=0;i<m;i++)scanf("%d%d%d",&data[i].x,&data[i].y,&data[i].len);int prelen=0;                      //pre数组的长度sort(data,data+m);//kruskal 前面的工作int ans=kruskal(n,m,prelen);        //正常版本的kruskalbool unique=true;           for(int i=0;i<prelen;i++){int res=kruskal2(n,m,pre[i].x,pre[i].y);//带去除边的kruskalint cnt=0;for(int j=1;j<=n;j++)if(fa[i]==i)cnt++;               if(cnt!=0)    //这个很重要!没有就WA,因为可能剩下的不连通,但是恰好res==anscontinue;if(res==ans)   //如果还有一棵生成树和第一次所求的权值一样,说明最小生成树不唯一{unique=false;break;}}if(unique)printf("%d\n",ans);elseprintf("Not Unique!\n");}return 0;}


4 0