The Unique MST POJ
阿新 • • 發佈:2018-12-10
從前有兩隻貓。它們實在不知道該出什麼題了。 於是它們放棄了治療,開始玩一個遊戲:從鄉鎮地圖中已有的道路里面刪除一些道路,並且刪除完畢後圖仍然是連通的。在所有方案中,刪除道路總長度最大的方案為最優方案。 兩隻貓同時完成了這個遊戲。它們都堅信自己是贏家。已知它們的完成方式不同,請判斷有沒有可能它們的實現方案都是最優的。
Input
第一行是一個整數 t (1 <= t <= 20), 測試用例的數量。每個用例代表一張圖,第一行是n和m (1 <= n <= 100), 分別為城鎮數和道路數。接下來m行為m個三元組 (xi, yi, wi),表示編號為xi和yi的城鎮被長度為wi的道路連線。兩個城鎮之間最多被一條道路連線。
Output
對於每個用例,如果答案為否定(即不可能都是最優方案),輸出最優方案剩餘的(注意不是刪除的)道路總長度。否則輸出字串 'Not Unique!'(不帶引號)。
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!
題解:這題要用到求次小生成樹的方法。具體就是在求最小生成樹的過程中把從點i到j的生成樹上的邊的最大權值記錄下來,用maxw[i][j]表示,那麼在最小生成樹上如果再加任意一條邊的話都會形成環,於是要讓圖成為生成樹的話就必須刪掉一條邊(除加上的邊以為),那麼刪的這條邊必須是原來i,j兩點的最大邊,才有可能次小,如果求出來的要刪的次小邊與新添的邊長度一樣,那麼就說明最小生成樹不止一個。
#include <stdio.h> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 110; int g[maxn][maxn],d[maxn],vis[maxn],link[maxn][maxn],maxw[maxn][maxn],pre[maxn],n,m; //link[i][j] 判斷i,j是否可以連通,pre[i]表示在生成樹中i的前一點是哪個 int prim() { memset(d,inf,sizeof(d)); memset(vis,0,sizeof(vis)); memset(maxw,0,sizeof(maxw)); for(int i = 1;i <= n;i++) pre[i] = 1; d[1] = 0; int sum = 0; while(1) { int v = -1; for(int u = 1;u <= n;u++) { if(!vis[u] && (v == -1 || d[v] > d[u])) v = u; } if(v == -1) break; vis[v] = 1; sum += d[v]; int pred = pre[v]; maxw[pred][v] = d[v]; for(int i = 1;i <= n;i++)//更新maxw[i][v] { maxw[i][v] = max(maxw[pred][v],maxw[i][pred]); } link[pred][v] = link[v][pred] = 0;//已經在樹中的點要標記為不可連通 for(int u = 1;u <= n;u++) { if(!vis[u] && d[u] > g[v][u]) { d[u] = g[v][u]; pre[u] = v; } } } return sum; } int main() { int t; scanf("%d",&t); while(t--) { memset(link,0,sizeof(link)); memset(g,inf,sizeof(g)); scanf("%d %d",&n,&m); for(int i = 1;i <= m;i++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); g[u][v] = g[v][u] = w; link[u][v] = link[v][u] = 1; } int ans = prim(); int flag = 0; for(int i = 1;i <= n;i++) { for(int j = 1;j <= n;j++) { if(!link[i][j] || g[i][j] == inf) continue; if(g[i][j] == maxw[i][j])//要刪的邊和加的邊權值相等 flag = 1; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }