次小生成樹,就是求除了最小生成樹之外最小的那個生成樹。
下面介紹一下利用prim求次小生成樹的主要步驟。
1.先求出來最小生成樹。並將最小生成樹任意兩點之間路徑當中的權值最大的那一條找出來,為什么要找最大的呢,因為生成樹加入一條邊之后一定構成了回路,那么肯定要去掉這個回路當中一條邊才是生成樹,那么,怎么去邊才是次小的,那就去掉除了剛剛添加的一條邊之外回路當中權值最大的一個,所以留下的就是最小的。
2.枚舉最小生成樹外的每一條邊。找出最小的就是次小生成樹。
POJ1679 The Unique MST
題意:給定圖,讓求它的最小生成樹是否唯一。如果唯一的話輸出最小生成樹的權值和,否則輸出Not Unique!
思路:直接求次小生成樹就行。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 111; const int inf = 0x3f3f3f3f; int Map[maxn][maxn];//鄰接矩陣存圖 int Max[maxn][maxn];//表示最小生成樹中i到j的最大邊權 bool used[maxn][maxn];//判斷該邊是否加入最小生成樹 int pre[maxn]; int dis[maxn]; void init(int n) { for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (i == j) Map[i][j] = 0; else Map[i][j] = inf; } void read(int m) { int u, v, w; for (int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); Map[u][v] = Map[v][u] = w; } } int prim(int n) { int ans = 0; bool vis[maxn]; memset(vis, false, sizeof(vis)); memset(used, false, sizeof(used)); memset(Max, 0, sizeof(Max)); for (int i = 2; i <= n; i++) { dis[i] = Map[1][i]; pre[i] = 1; } pre[1] = 0; dis[1] = 0; vis[1] = true; for (int i = 2; i <= n; i++) { int min_dis = inf, k; for (int j = 1; j <= n; j++) { if (!vis[j] && min_dis > dis[j]) { min_dis = dis[j]; k = j; } } if (min_dis == inf) return -1;//如果不存在最小生成樹 ans += min_dis; vis[k] = true; used[k][pre[k]] = used[pre[k]][k] = true; for (int j = 1; j <= n; j++) { if (vis[j]) Max[j][k] = Max[k][j] = max(Max[j][pre[k]], dis[k]); if (!vis[j] && dis[j] > Map[k][j]) { dis[j] = Map[k][j]; pre[j] = k; } } } return ans;//最小生成樹的權值之和 } int smst(int n, int min_ans)//min_ans 是最小生成樹的權值和 { int ans = inf; for (int i = 1; i <= n; i++)//枚舉最小生成樹之外的邊 for (int j = i + 1; j <= n; j++) if (Map[i][j] != inf && !used[i][j]) ans = min(ans, min_ans + Map[i][j] - Max[i][j]); if (ans == inf) return -1; return ans; } void solve(int n) { int ans = prim(n); if (ans == -1) { puts("Not Unique!"); return; } if (smst(n, ans) == ans) printf("Not Unique!\n"); else printf("%d\n", ans); } int main() { int T, n, m; scanf("%d", &T); while (T--) { scanf("%d %d", &n, &m); init(n); read(m); solve(n); } return 0; }
