POJ_1679_The Unique MST(次小生成樹模板)
阿新 • • 發佈:2017-07-05
div 題目 矩陣 gson direct style data connected include
The Unique MST
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V‘, E‘), with the following properties:
1. V‘ = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E‘) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E‘.
The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the
following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.
For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!‘.
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 23942 | Accepted: 8492 |
Description
Given a connected undirected graph, tell if its minimum spanning tree is unique.Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V‘, E‘), with the following properties:
1. V‘ = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E‘) of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E‘.
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的唯一路徑中權
值最大的那條邊的權值。註意這裏是非常easy做到的。由於Prime是每次添加一個節點t。而設已經標了號的節點集合為S,則S
中全部節點到t的路徑中最大權值的邊就是當前增加的這條邊。
(2)枚舉最小生成樹以外的邊,並刪除該邊所在環上權值最大的邊。
(3)取得的全部生成樹中權值最小的一棵即為所求。
算法的時間復雜度為O(n^2)。
題目鏈接:
id=1679">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; }
POJ_1679_The Unique MST(次小生成樹模板)