求权值最小的桥,考虑几种特殊情况:
- 图本身不连通,那么就不用派人去了
- 图的边双连通分量只有一个,答案是-1
- 桥的最小权值是0,但是也要派一个人过去
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <stack> 7 using namespace std; 8 9 const int maxn = 1000 + 10; 10 const int maxm = 1000000 + 10; 11 12 int n, m; 13 14 int cc; 15 int pa[maxn]; 16 int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); } 17 18 void Union(int x, int y) 19 { 20 int px = findset(x), py = findset(y); 21 if(px != py) { pa[px] = py; cc--; } 22 } 23 24 struct Edge 25 { 26 int v, nxt, w; 27 }edges[maxm * 2]; 28 int ecnt; 29 int head[maxn]; 30 31 void AddEdge(int u, int v, int d) 32 { 33 edges[ecnt].v = v; 34 edges[ecnt].w = d; 35 edges[ecnt].nxt = head[u]; 36 head[u] = ecnt++; 37 } 38 39 stack<int> S; 40 bool isbridge[maxm * 2]; 41 int dfs_clock, scc_cnt; 42 int low[maxn], pre[maxn], sccno[maxn]; 43 44 void dfs(int u, int fa) 45 { 46 pre[u] = low[u] = ++dfs_clock; 47 S.push(u); 48 49 for(int i = head[u]; ~i; i = edges[i].nxt) 50 { 51 if(i == (fa ^ 1)) continue; 52 int v = edges[i].v; 53 if(!pre[v]) 54 { 55 dfs(v, i); 56 low[u] = min(low[u], low[v]); 57 if(low[v] > low[u]) isbridge[i] = true; 58 } 59 else if(!sccno[v]) low[u] = min(low[u], pre[v]); 60 } 61 62 if(low[u] == pre[u]) 63 { 64 scc_cnt++; 65 for(;;) 66 { 67 int x = S.top(); S.pop(); 68 sccno[x] = scc_cnt; 69 if(x == u) break; 70 } 71 } 72 } 73 74 void find_scc() 75 { 76 dfs_clock = scc_cnt = 0; 77 memset(isbridge, false, sizeof(isbridge)); 78 memset(pre, 0, sizeof(pre)); 79 memset(sccno, 0, sizeof(sccno)); 80 for(int i = 1; i <= n; i++) if(!pre[i]) dfs(i, -1); 81 } 82 83 int main() 84 { 85 while(scanf("%d%d", &n, &m) == 2 && n) 86 { 87 ecnt = 0; 88 memset(head, -1, sizeof(head)); 89 cc = n; 90 for(int i = 1; i <= n; i++) pa[i] = i; 91 while(m--) 92 { 93 int u, v, d; scanf("%d%d%d", &u, &v, &d); 94 Union(u, v); 95 AddEdge(u, v, d); AddEdge(v, u, d); 96 } 97 98 if(cc > 1) { puts("0"); continue; } 99 100 find_scc(); 101 102 if(scc_cnt == 1) { puts("-1"); continue; } 103 104 int ans = 1000000000; 105 for(int i = 0; i < ecnt; i += 2) if(isbridge[i]) ans = min(ans, edges[i].w); 106 if(!ans) ans = 1; 107 printf("%d ", ans); 108 } 109 110 return 0; 111 }