hdu 4738 无向图求桥

  1 /*
  2 题意:给出n个岛屿,m座桥连接,每座桥由w个人守住,给出一个炸弹可以炸毁一座桥,而炸每座桥之前
  3 要先将桥上的敌人消灭,最少需要w人,问最少需要多少人才能炸毁其中的一座桥
  4 
  5 题解:无向图求桥
  6 注意:有重边,当桥上人数为0时,最少应该需要1人(需要有一个人带着炸弹过去)
  7 */
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <algorithm>
 11 
 12 using namespace std;
 13 
 14 #define MAXN 1005
 15 #define MAXM 1000005
 16 
 17 const int INF = 100000;
 18 
 19 struct node {
 20     int v, w, pre, id;  //id:边的编号(处理重边情况)
 21 } edge[MAXM];
 22 int pos[MAXN], nEdge; //图的存储:链式前向星(池子法)
 23 
 24 struct Bridge {
 25     int u, v, w;
 26 } bridge[MAXM];  //用来记录桥
 27 int tot; //桥的个数
 28 
 29 int fa[MAXN], cc; //fa:各个点所属的缩点(连通块),cc连通块的个数
 30 int dfn[MAXN], low[MAXN], time; //时间戳
 31 int stack[MAXN], top;   //用于维护连通块的
 32 int n, m;   //点的个数和边的条数
 33 
 34 void connect(int u, int v, int w, int id) { 
 35     nEdge++;
 36     edge[nEdge].pre = pos[u];
 37     edge[nEdge].v = v;
 38     edge[nEdge].w = w;
 39     edge[nEdge].id = id;
 40     pos[u] = nEdge;
 41 }
 42 
 43 void tarjan(int cur, int from) {
 44     low[cur] = dfn[cur] = time++;
 45     stack[++top] = cur;
 46     for (int p=pos[cur]; p; p=edge[p].pre) {
 47         int v = edge[p].v;
 48         if (edge[p].id == from) continue;
 49         if (!dfn[v]) {
 50             tarjan(v, edge[p].id);
 51             if (low[v] < low[cur]) low[cur] = low[v];
 52             if (low[v] > dfn[cur]) {
 53                 bridge[tot].u = cur;
 54                 bridge[tot].w = edge[p].w;
 55                 bridge[tot++].v = v;
 56                 cc++;
 57                 do {
 58                     fa[stack[top]] = cc;
 59                 } while (stack[top--] != v);
 60             }
 61         } else if (low[cur] > dfn[v]) low[cur] = dfn[v];
 62     }
 63 }
 64 int main(void) 
 65 {
 66     while(~scanf("%d%d", &n, &m), n || m)
 67     {
 68         memset(pos, 0, sizeof(pos));
 69         nEdge = 0;
 70         int u, v, w;
 71         for (int i=0; i<m; i++) {
 72             scanf("%d%d%d", &u, &v, &w);
 73             connect(u, v, w, i);
 74             connect(v, u, w, i);
 75         }
 76 
 77         memset(dfn, 0, sizeof(dfn));
 78         memset(fa, -1, sizeof(fa));
 79 
 80         cc = tot = 0;
 81         if (!dfn[1]) {
 82             top = time = 1;
 83             tarjan(1, -1);
 84             ++cc;
 85             int j;
 86             for (j=1; j<=n; j++)   //特殊处理顶点的连通块
 87             {
 88                 if (dfn[j])
 89                 {
 90                     if (fa[j] == -1)
 91                         fa[j] = cc;
 92                 }
 93                 else
 94                     break;
 95             }
 96             if (j <= n)
 97                 printf("0\n");
 98             else
 99             {
100                 int minw = INF;
101                 if (tot > 0)
102                 {
103                     for(int i=0; i<tot; i++)
104                         minw = min(bridge[i].w,minw);
105                     if (minw == 0)
106                         minw = 1;
107                     printf("%d\n",minw);
108                 }
109                 else
110                     printf("-1\n");
111             }
112         }
113     }
114     return 0;
115 }

 

posted @ 2014-04-07 19:11  辛力啤  阅读(199)  评论(0编辑  收藏  举报