zoukankan      html  css  js  c++  java
  • 【HDU 4738 Caocao's Bridges】BCC 找桥

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738

    题意:给定一个n个节点m条边的无向图(可能不连通、有重边),每条边有一个权值。判断其连通性,若双连通,输出-1;若非连通,输出0;否则,输出权值最小的桥的权值。

    思路:进行双连通域分解,记下连通块的个数和所有桥的情况,对应输出结果即可。

    注意对重边的处理。这里我按照上一道题学到的姿势如法炮制:先把所有边按“字典序”排序(u, v, w),这样重边聚集在一起了,然后扫描一遍,发现重边即在结构体Edge中打重边标记;由于重边一定不是桥,因此选哪个的权值实际上无所谓。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <vector>
      5 #define CLEAR(A, X) memset(A, X, sizeof(A))
      6 #define REP(N) for(int i=0; i<(N); i++)
      7 #define REPE(N) for(int i=1; i<=(N); i++)
      8 #define FREAD(FN) freopen((FN), "r", stdin)
      9 #define pb(a) push_back(a)
     10 
     11 using namespace std;
     12 
     13 const int MAX_N = 1005;
     14 const int MAX_M = 2000005;
     15 const int INF = 10005;
     16 int n, m;
     17 
     18 struct Edge
     19 {
     20     int v, next;
     21     int w;
     22     bool isBrg;
     23     bool isDup;
     24 }edges[MAX_M];
     25 int numE;
     26 int head[MAX_N];
     27 int low[MAX_N], dfn[MAX_N], clock;
     28 int inStack[MAX_N], S[MAX_N], topS;
     29 int block, belong[MAX_N];
     30 int numBrg;
     31 int cnt;//连通块个数
     32 
     33 void init(){
     34     numE = 0;
     35     clock = block = topS = 0;
     36     numBrg = 0;
     37     CLEAR(low, 0);
     38     CLEAR(dfn, 0);
     39     CLEAR(head, -1);
     40     CLEAR(belong, 0);
     41     CLEAR(inStack, 0);
     42 }
     43 
     44 
     45 void addEdge(int u, int v, int w, bool isDup){
     46     edges[numE].v = v;
     47     edges[numE].w = w;
     48     edges[numE].isBrg = 0;
     49     edges[numE].isDup = isDup;
     50     edges[numE].next = head[u];
     51     head[u] = numE++;
     52 
     53     //反向边
     54     edges[numE].v = u;
     55     edges[numE].w = w;
     56     edges[numE].isBrg = 0; //这里之前忘清零了,一直WA。。。
     57     edges[numE].isDup = isDup;
     58     edges[numE].next = head[v];
     59     head[v] = numE++;
     60 }
     61 
     62 void bcc(int u, int p, int isDup){
     63     low[u] = dfn[u] = ++clock;
     64     S[topS++] = u;
     65     inStack[u] = 1;
     66     for(int i=head[u]; i != -1; i = edges[i].next){
     67         int v = edges[i].v;
     68         if(v == p && (!isDup)) continue;
     69         if(!dfn[v]){
     70             bcc(v, u, edges[i].isDup);
     71             low[u] = min(low[u], low[v]);
     72             if(low[v] > dfn[u]){//bridge
     73                 numBrg++;
     74                 edges[i].isBrg = 1;
     75                 edges[i^1].isBrg = 1;
     76             }
     77         }else if(inStack[v]){//backward
     78             low[u] = min(low[u], dfn[v]);
     79         }
     80     }
     81     if(low[u] == dfn[u]){//new bcc
     82         block++;
     83         int t;
     84         do{
     85             t = S[--topS];
     86             inStack[t] = 0;
     87             belong[t] = block;
     88         }while(t != u);
     89     }
     90 }
     91 
     92 struct Node
     93 {
     94     int u, v, w;
     95     Node(){}
     96     Node(int uu, int vv, int ww):u(uu), v(vv), w(ww){}
     97 }nodes[MAX_M];
     98 bool cmp(Node a, Node b){
     99     if(a.u == b.u){
    100         if(a.v == b.v) return a.w < b.w;
    101         return a.v < b.v;
    102     }
    103     return a.u < b.u;
    104 }
    105 bool same(Node a, Node b){
    106     return a.u == b.u && a.v == b.v;
    107 }
    108 
    109 int main()
    110 {
    111     FREAD("4738.txt");
    112     while(~scanf("%d%d", &n, &m) && !(n==0 && m==0)){
    113         init();
    114         REP(m){
    115             int u, v, w;
    116             scanf("%d%d%d", &u, &v, &w);
    117             if(u > v) swap(u, v);//保持顺序
    118             nodes[i] = Node(u, v, w);
    119         }
    120         sort(nodes, nodes+m, cmp);
    121         int cur = 0, i = 1;
    122         int flagDup = 0;
    123         while(cur < m){
    124             while(i < m && same(nodes[cur], nodes[i])){
    125                 flagDup = 1;
    126                 i++;
    127             }//重边一定不是桥,
    128             if(flagDup) addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, true);
    129             else addEdge(nodes[cur].u, nodes[cur].v, nodes[cur].w, false);
    130             flagDup = 0;
    131             cur = i++;
    132         }
    133         cnt = 0;
    134         REPE(n){
    135             if(!dfn[i]){
    136                 bcc(i, 0, 0);
    137                 cnt++;
    138             }
    139         }
    140         int ans = INF;
    141         if(cnt > 1) ans = 0;//非连通
    142         else if(cnt==1 && !numBrg) ans = -1;//边双连通
    143         else{//有桥
    144             // REPE(n){
    145             //     for(int j=head[i]; j != -1; j = edges[j].next){
    146             //         int v = edges[j].v;
    147             //         if(belong[i] != belong[v])
    148             //             ans = min(ans, edges[j].w);
    149             //     }
    150             // }
    151             REPE(numE){
    152                 if(edges[i].isBrg)
    153                     ans = min(ans, edges[i].w);
    154             }
    155             if(ans == 0) ans = 1;//至少派一人
    156         }
    157         printf("%d
    ", ans);
    158     }
    159     return 0;
    160 }

    判桥用 edges[i].isBrg 或 belong[u] == belong[v]都可以,二者等价。

    多组样例,我开始用第一种但忘记在addEdge中把isBrg清零了才会WA。

  • 相关阅读:
    121.买卖股票 求最大收益1 Best Time to Buy and Sell Stock
    409.求最长回文串的长度 LongestPalindrome
    202.快乐数 Happy Number
    459.(KMP)求字符串是否由模式重复构成 Repeated Substring Pattern
    326.是否为3的平方根 IsPowerOfThree
    231.是否为2的平方根 IsPowerOfTwo
    461.求两个数字转成二进制后的“汉明距离” Hamming Distance
    206.反转单链表 Reverse Linked List
    448. 数组中缺少的元素 Find All Numbers Disappeared in an Array
    常见表单元素处理
  • 原文地址:https://www.cnblogs.com/helenawang/p/5556110.html
Copyright © 2011-2022 走看看