Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 23942 | Accepted: 8492 |
Description
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
题意:问最小生成树是否唯一。
分析:求次小生成树,判断次小生成树和最小生成树是否相等。留作模板。
次小生成树的步骤:
(1)先用Prime求出最小生成树T,在Prime的同时用一个矩阵max_edge[u][v]记录在T中连接任意两点u,v的唯一路径中权
值最大的那条边的权值。注意这里是很容易做到的,因为Prime是每次增加一个节点t,而设已经标了号的节点集合为S,则S
中所有节点到t的路径中最大权值的边就是当前加入的这条边。
(2)枚举最小生成树以外的边,并删除该边所在环上权值最大的边。
(3)取得的所有生成树中权值最小的一棵即为所求。
算法的时间复杂度为O(n^2)。
题目链接:http://poj.org/problem?id=1679
代码清单:
#include<set> #include<map> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<string> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 100 + 5; const int maxv = 10000 + 5; const int max_dis = 1e9 + 5; int T; int n,m; int a,b,c; int MST,_MST; bool vis[maxn]; int father[maxn]; int dist[maxn]; int graph[maxn][maxn]; bool used[maxn][maxn]; int max_edge[maxn][maxn]; void init(){ memset(vis,false,sizeof(vis)); memset(used,false,sizeof(used)); memset(max_edge,-1,sizeof(max_edge)); memset(graph,0x7f,sizeof(graph)); } void input(){ scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); graph[a][b]=graph[b][a]=c; used[a][b]=used[b][a]=true; } } int prim(){ int ans=0; dist[1]=0; vis[1]=true; father[1]=-1; for(int i=2;i<=n;i++){ father[i]=1; dist[i]=graph[1][i]; } for(int i=1;i<n;i++){ int v=-1; for(int j=1;j<=n;j++){ if(!vis[j]&&(v==-1||dist[j]<dist[v])) v=j; } ans+=dist[v]; vis[v]=true; used[father[v]][v]=used[v][father[v]]=false; for(int j=1;j<=n;j++){ if(vis[j]){ max_edge[v][j]=max_edge[j][v]=max(max_edge[father[v]][j],dist[v]); } else{ if(graph[v][j]<dist[j]){ dist[j]=graph[v][j]; father[j]=v; } } } }return ans; } int second_prim(){ int ans=max_dis; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(used[i][j]) ans=min(ans,MST+graph[i][j]-max_edge[i][j]); return ans; } void solve(){ MST=prim(); _MST=second_prim(); if(MST==_MST) printf("Not Unique!\n"); else printf("%d\n",MST); } int main(){ scanf("%d",&T); while(T--){ init(); input(); solve(); }return 0; }