HDU 4738 双连通分量 Caocao's Bridges

求权值最小的桥,考虑几种特殊情况:

  • 图本身不连通,那么就不用派人去了
  • 图的边双连通分量只有一个,答案是-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\n", ans);
108     }
109 
110     return 0;
111 }
代码君

 

posted @ 2015-08-12 09:32  AOQNRMGYXLMV  阅读(192)  评论(0编辑  收藏  举报