又是生成树问题。。。次小生成树,顾名思义就是比最小稍微大那么一点点的生成树,^_^
方法是:
1、找到最小生成树,值为mst
2、最小生成树种的点:找到每一个点到其它点的路径上的最大边权值 dp[i][j]表示i到j路径上的最大边权值
3、加一条不在最小生成树上的边。比如i - k,同时删除在最小生成树上i -> k路径上最大的一个边权值dp[i][k]; 这样会得到 new_mst,在这些new_mst中找一个最小的,就是次小生成树的值
实现上用到一些技巧,代码如下POJ 1679:
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #include <map> #include <sstream> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x)) const int eps = 1e-6; const int inf = ~0u>>2; typedef long long LL; using namespace std; const int N = 110; const int M = 100000; struct node { int to; int next; } G[M]; int mp[N][N]; int dis[N]; int pre[N]; bool vis[N]; int head[N], t; int n; bool inMST[N][N]; int dp[N][N]; void add(int u, int v) { G[t].to = v; G[t].next = head[u]; head[u] = t++; } int prim() { int i, j, f, mx, ret = 0; for(i = 1; i <= n; ++i) { dis[i] = inf; pre[i] = 0; vis[i] = false; } pre[1] = 0; dis[1] = 0; for(i = 1; i <= n; ++i) { mx = inf; f = 0; for(j = 1; j <= n; ++j) { if(!vis[j] && mx > dis[j]) { mx = dis[j]; f = j; } } vis[f] = true; ret += mx; for(j = 1; j <= n; ++j) { if(!vis[j] && dis[j] > mp[f][j]) { pre[j] = f; dis[j] = mp[f][j]; } } } for(i = 1; i <= n; ++i) { //记录在最小生成树上的边 if(pre[i]) inMST[pre[i]][i] = inMST[i][pre[i]] = true; } for(i = 1; i <= n; ++i) { //建新图,用来找在最小生成树上 i->j路径中最大的一个边权值 if(pre[i]) {add(pre[i], i); add(i, pre[i]); } //printf("%d %d ", i , pre[i]); } return ret; } void init() { int i, j; for(i = 1; i <= n; ++i) { for(j = 1; j <= n; ++j) { mp[i][j] = (i == j ? 0 : inf); } } CL(head, -1); t = 0; CL(inMST, false); CL(dp, 0); } void dfs(int st, int to, int val) { //。。。 vis[to] = true; dp[st][to] = val; for(int i = head[to]; i != -1; i = G[i].next) { if(!vis[G[i].to]) dfs(st, G[i].to, max(val, mp[to][G[i].to])); } } int main() { //freopen("data.in", "r", stdin); int t, m, i, j; int u, v, w; int ans, mst; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); init(); while(m--) { scanf("%d%d%d", &u, &v, &w); mp[u][v] = mp[v][u] = w; } mst = prim(); ans = inf; for(i = 1; i <= n; ++i) { CL(vis, false); dfs(i, i, 0); } for(i = 1; i <= n; ++i) { for(j = i + 1; j <= n; ++j) { if(!inMST[i][j] && mp[i][j] != inf) //加边 ans = min(ans, mst - dp[i][j] + mp[i][j]); } } if(ans == mst) puts("Not Unique!"); else printf("%d ", mst); } return 0; }