#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 100+10;
vector<int>E[maxn], W[maxn];
int fa[maxn];
int maxlen[maxn][maxn];
int nodepre[maxn], npre;
struct Edge {
int u, v, w;
bool operator < (const Edge & rhs) const {
return w < rhs.w;
}
}e[maxn*maxn];
int find(int x) {
return fa[x] == x ? x : find(fa[x]);
}
void dfs(int u, int fa) { // nodepre 保存前面訪問過的點,對於邊(u,v)-> maxlen[pre][v] = max(maxlen[pre][v], W[u][i]);
nodepre[npre++] = u;
for( int i=0; i<E[u].size(); i++ ) {
int v = E[u][i];
if(v == fa) continue;
maxlen[u][v] = maxlen[v][u] = W[u][i];
for( int j=0; j<npre; j++ ) {
int pre = nodepre[j];
maxlen[pre][v] = max(maxlen[pre][u], W[u][i]);
maxlen[v][pre] = maxlen[pre][v];
}
dfs(v, u);
}
}
int main() {
freopen("in", "r", stdin);
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", &e[i].u, &e[i].v, &e[i].w);
}
sort(e, e + m);
for( int i=1; i<=n; i++ ) E[i].clear(), W[i].clear();
for( int i=1; i<=n; i++ ) fa[i] = i;
int tn = n, ti;
int cost = 0;
for( int i=0; i<m; i++ ) { // kruscal 算法
int u = e[i].u, v = e[i].v, w = e[i].w;
int x = find(u);
int y = find(v);
if(x != y) {
fa[x] = y;
E[u].push_back(v); W[u].push_back(w);
E[v].push_back(u); W[v].push_back(w);
tn--;
cost += w;
if(tn == 1) {
ti = i+1;
break;
}
}
}
npre = 0;
for( int i=1; i<=n; i++ ) for( int j=1; j<=n; j++ ) maxlen[i][j] = 0;
dfs(1, -1); // 求最小生成樹上任兩個間路徑最長的邊
bool flag = true;
for( int i=ti; i<m; i++ ) { // 枚舉後面沒用過的邊
int u = e[i].u, v = e[i].v, w = e[i].w;
if(cost == cost + w - maxlen[u][v]) { // 如果相等說明最小生成樹不唯一
flag = false;
break;
}
}
if(flag) printf("%d\n", cost);
else printf("Not Unique!\n");
}
return 0;
}
POJ 1679 The Unique MST (次小生成樹)
題目類型 次小生成樹
題目意思
給出 n 個點 m 條邊問最小生成樹是否唯一 (n <= 100)
解題方法
先用kruscal算法求出最小生成樹和構成最小生成樹的邊 然後對於這棵最小生成樹用 dfs 求出任兩點間路徑上最長的一條邊是多少
然後枚舉剛纔後面沒用過的邊 (u, v) , 新的生成樹的最小花費是
w(u,v) - maxlen[u][v] (即現在枚舉的邊的權值 - 最小生成樹上u,v間路徑上最長的一條邊)
參考代碼 - 有疑問的地方在下方留言 看到會盡快回復的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.