//本周依旧做一下图算法的题目,尽量少用algorithm里的函数,自己写熟悉熟悉。
解析:该题为次小生成树问题。
次小生成树的求解过程:
1、找到最小生成树,值为mst
2、最小生成树种的点:找到每一个点到其它点的路径上的最大边权值 dp[i][j]表示i到j路径上的最大边权值
3、加一条不在最小生成树上的边。比如i - k,同时删除在最小生成树上i -> k路径上最大的一个边权值dp[i][k]; 这样会得到 new_mst,在这些new_mst中找一个最小的,就是次小生成树的值
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <string> 6 #include <cstring> 7 8 using namespace std; 9 10 #define INF 1000000007 11 #define MAXN 105 12 #define MAX(a, b) (a > b ? a : b) 13 #define MIN(a, b) (a < b ? a : b) 14 15 struct Edge 16 { 17 int v; 18 int next; 19 }edge[100010]; 20 21 int t, n, m, T; 22 int d[MAXN], vis[MAXN], pre[MAXN], head[MAXN]; 23 int g[MAXN][MAXN], dp[MAXN][MAXN], in_mst[MAXN][MAXN]; 24 25 void init() 26 { 27 t = 0; 28 for (int i = 0; i <= n; ++i) 29 for (int j = 0; j <= n; ++j) 30 g[i][j] = (i == j ? 0 : INF); 31 memset(head, -1, sizeof(head)); 32 memset(in_mst, 0, sizeof(in_mst)); 33 memset(dp, 0, sizeof(dp)); 34 } 35 36 void addEdge(int u, int v) 37 { 38 edge[t].v = v; 39 edge[t].next = head[u]; 40 head[u] = t++; 41 } 42 43 int prim() 44 { 45 int ans = 0; 46 47 for (int i = 1; i <= n; ++i) 48 d[i] = INF, pre[i] = 0, vis[i] = 0; 49 pre[1] = 0, d[1] = 0; 50 for (int i = 1; i <= n; ++i) 51 { 52 int min_cost = INF, idx = 0; 53 for (int j = 1; j <= n; ++j) 54 if (!vis[j] && min_cost > d[j]) 55 min_cost = d[idx = j]; 56 vis[idx] = 1; 57 ans += min_cost; 58 for (int j = 1; j <= n; ++j) 59 if (!vis[j] && d[j] > g[idx][j]) 60 d[j] = g[idx][j], pre[j] = idx; 61 } 62 for (int i = 1; i <= n; ++i) 63 if (pre[i]) in_mst[pre[i]][i] = in_mst[i][pre[i]] = 1; 64 for (int i = 1; i <= n; ++i) 65 if (pre[i]) 66 addEdge(pre[i], i), addEdge(i, pre[i]); 67 68 return ans; 69 } 70 71 void dfs(int u, int v, int w) 72 { 73 vis[v] = 1; 74 dp[u][v] = w; 75 for (int e = head[v]; e != -1; e = edge[e].next) 76 if (!vis[edge[e].v]) 77 dfs(u, edge[e].v, max(w, g[v][edge[e].v])); 78 } 79 80 int main() 81 { 82 scanf("%d", &T); 83 while (T--) 84 { 85 scanf("%d%d", &n, &m); 86 init(); 87 int u, v, w; 88 while (m--) 89 { 90 scanf("%d%d%d", &u, &v, &w); 91 g[u][v] = g[v][u] = w; 92 } 93 int mst = prim(); 94 int ans = INF; 95 for (int i = 1; i <= n; ++i) 96 { 97 memset(vis, 0, sizeof(vis)); 98 dfs(i, i, 0); 99 } 100 for (int i = 1; i <= n; ++i) 101 for (int j = i+1; j <= n; ++j) 102 if (!in_mst[i][j] && g[i][j] != INF) 103 ans = min(ans, mst-dp[i][j]+g[i][j]); 104 if (ans == mst) puts("Not Unique!"); 105 else printf("%d\n", mst); 106 } 107 108 return 0; 109 }
时间: 2024-10-06 08:14:43