• POJ 3694 Network (tarjan + LCA)


    题目链接:http://poj.org/problem?id=3694

    题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥。

    首先用tarjan标记点的low和dfn值,那么u和v相连的边是桥的条件是dfn[u] < low[v](说明v与u不在一个连通分量里面,v无法通过回溯到达u点,画个图模拟会清楚)。那么bridge[v]++表示u与v相连的边是桥(若是标记bridge[u]++,则最后的答案可能会出错,亲测)。要是u和v相连,不属于同一个连通分量的话会形成一个环路,那么环路里所有的桥都没有了,所以用LCA将u和v一边找公共祖节点,一边消除桥。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 const int MAXN = 2e5 + 5;
      7 struct data {
      8     int next , to;
      9 }edge[MAXN * 4];
     10 int head[MAXN] , block[MAXN] , low[MAXN] , dfn[MAXN] , st[MAXN] , dep[MAXN] , par[MAXN] , bridge[MAXN];
     11 int top , ord , sccnum , cont , ans;
     12 bool instack[MAXN];
     13 
     14 void init() {
     15     memset(head , -1 , sizeof(head));
     16     memset(low , 0 , sizeof(low));
     17     memset(dfn , 0 , sizeof(dfn));
     18     memset(instack , false , sizeof(instack));
     19     memset(bridge , 0 , sizeof(bridge));
     20     top = ord = sccnum = cont = ans = 0;
     21 }
     22 
     23 inline void add(int u , int v) {
     24     edge[cont].next = head[u];
     25     edge[cont].to = v;
     26     head[u] = cont++;
     27 }
     28 
     29 void tarjan(int u , int p , int d) {
     30     low[u] = dfn[u] = ++ord;
     31     st[++top] = u;
     32     instack[u] = true;
     33     par[u] = p;
     34     dep[u] = d;
     35     for(int i = head[u] ; ~i ; i = edge[i].next) {
     36         int v = edge[i].to;
     37         if(v == p)
     38             continue;
     39         if(!dfn[v]) {
     40             tarjan(v , u , d + 1);
     41             low[u] = min(low[v] , low[u]);
     42             if(dfn[u] < low[v]) {
     43                 bridge[v]++;
     44                 ans++;
     45             }
     46         }
     47         else if(instack[v]) {
     48             low[u] = min(low[u] , dfn[v]);
     49         }
     50     }
     51     if(low[u] == dfn[u]) {
     52         int v;
     53         sccnum++;
     54         do {
     55             v = st[top--];
     56             instack[v] = false;
     57             block[v] = sccnum;
     58         }while(u != v);
     59     }
     60 }
     61 
     62 void lca(int u , int v) {
     63     while(dep[u] < dep[v]) {
     64         if(bridge[v]) {
     65             ans--;
     66             bridge[v]--;
     67         }
     68         v = par[v];
     69     }
     70     while(dep[u] > dep[v]) {
     71         if(bridge[u]) {
     72             ans--;
     73             bridge[u]--;
     74         }
     75         u = par[u];
     76     }
     77     while(v != u) {
     78         if(bridge[u]) {
     79             bridge[u]--;
     80             ans--;
     81         }
     82         if(bridge[v]) {
     83             bridge[v]--;
     84             ans--;
     85         }
     86         u = par[u];
     87         v = par[v];
     88     }
     89 }
     90 
     91 int main()
     92 {
     93     int n , m , u , v , q , Case = 1;
     94     while(~scanf("%d %d" , &n , &m) && (n || m)) {
     95         init();
     96         while(m--) {
     97             scanf("%d %d" , &u , &v);
     98             add(u , v);
     99             add(v , u);
    100         }
    101         tarjan(1 , -1 , 0);
    102         scanf("%d" , &q);
    103         printf("Case %d:
    " , Case++);
    104         while(q--) {
    105             scanf("%d %d" , &u , &v);
    106             if(block[u] == block[v]) {
    107                 printf("%d
    " , ans);
    108                 continue;
    109             }
    110             lca(u , v);
    111             printf("%d
    " , ans);
    112         }
    113         putchar('
    ');
    114     }
    115 }
  • 相关阅读:
    cogs 1272. [AHOI2009] 行星序列
    1027. 打印沙漏(20)
    1026. 程序运行时间(15)
    1023. 组个最小数 (20)
    《C语言程序设计(第四版)》阅读心得(四 文件操作)
    1022. D进制的A+B (20)
    1021. 个位数统计 (15)
    1020. 月饼 (25)
    1015. 德才论 (25)
    1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/Recoder/p/5267176.html
Copyright © 2020-2023  润新知