標籤:style io for sp on c amp size r
次小產生樹
求最小產生樹時,用數組Max[i][j]來表示MST中i到j的最大邊權。
求完後,直接枚舉所有不在MST中的邊,替換掉最大邊權的邊,更新答案。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 110;const int INF = 1e9;bool vis[maxn];int d[maxn];int pre[maxn];int Max[maxn][maxn];bool used[maxn][maxn];int g[maxn][maxn];int n, m;int Prim(){ int ans = 0; memset(vis, false, sizeof vis ); memset(Max, 0, sizeof Max ); memset(used, false, sizeof used ); vis[0] = true; pre[0] = -1; for(int i=1; i<n; ++i) { d[i] = g[0][i]; pre[i] = 0; } for(int i=1; i<n; ++i) { int p = -1; for(int j=0; j<n; ++j) if(!vis[j] && (p==-1||d[p]>d[j])) p = j; if(-1==p) return -1; ans += d[p]; vis[p] = true; used[p][pre[p]] = used[pre[p]][p] = true; for(int j=0; j<n; ++j) { if(vis[j]) Max[j][p] = Max[p][j] = max(Max[j][pre[p]], d[p]); if(!vis[j]&&d[j]>g[p][j]) { d[j] = g[p][j]; pre[j] = p; } } } return ans;}void solve(){ int res = Prim(); if(-1 == res) { //圖不連通 puts("Not Unique!"); return ; } int Mn = INF; for(int i=0; i<n; ++i) for(int j=i+1; j<n; ++j) if(g[i][j]!=INF && !used[i][j]) { Mn = min(Mn, g[i][j]-Max[i][j]); } if(Mn==INF || Mn!=0){ //不存在次小產生樹 或 不相等 printf("%d\n", res); }else { puts("Not Unique!"); }}int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) g[i][j] = INF; int x, y, z; while(m--) { scanf("%d%d%d", &x, &y, &z); x--; y--; g[x][y] = g[y][x] = z; } solve(); } return 0;}
poj 1679 The Unique MST,次小產生樹