• poj3694(动态询问割桥的数目)


    给我们一个图,然后有q次加边的操作,问每次加完边之后有多少个桥存在

    首先用dfs求出所有的桥,然后dfs的过程中生成了一棵dfs树,该树有的边是桥,有的不是,用bridge[v] = true , 表示v与fa[v]的连边是桥

    当加入一个边u,v后, u,v,lca(u,v)上的边从割边变成了非割边。

    至于lca,我们可以用dfs过程中的dfn标号来向上回溯。

    因为dfn[u] > dfn[lca(u,v)], dfn[v] > dfn[lca(u,v])

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <math.h>
      5 #include <algorithm>
      6 #include <vector>
      7 #include <stack>
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 #include <functional>
     12 using namespace std;
     13 
     14 const int N = 100000+10;
     15 int head[N],next[N*4],to[N*4],e;
     16 int dfn[N],low[N],dfs_clock,cut,bridge[N],pre[N];
     17 
     18 void init(int n)
     19 {
     20     e = dfs_clock = cut = 0;
     21     memset(head,-1,sizeof(head));
     22     for(int i=1;i<=n;++i)
     23     {
     24         fa[i] = i;
     25         dfn[i] = low[i] = bridge[i] = 0;
     26     }
     27 }
     28 void addEdge(int u, int v)
     29 {
     30     to[e] = v;
     31     next[e] = head[u];
     32     head[u] = e++;
     33 }
     34 
     35 void tarjan(int u, int f)
     36 {
     37     dfn[u] = low[u] = ++dfs_clock;
     38     bool flag  = false;
     39     for(int i=head[u]; i!=-1; i=next[i])
     40     {
     41         int v = to[i];
     42         if(v==f && !flag)
     43         {
     44             flag=true;
     45             continue;
     46         }
     47         if(dfn[v]==0)
     48         {
     49             pre[v] = u;
     50             tarjan(v,u);
     51         }
     52         low[u] = min(low[v],low[u]);
     53         if(low[v] > dfn[u])
     54         {
     55             bridge[v] = true;
     56             cut++;
     57         }
     58     }
     59 }
     60 
     61 void lca(int u, int v)
     62 {
     63     if(dfn[u] < dfn[v])
     64         swap(u,v);
     65     while(dfn[u] > dfn[v])//回溯完后u就是lca
     66     {
     67 
     68        if(bridge[u])
     69        {
     70            cut--;
     71            bridge[u] = false;
     72        }
     73         u = pre[u];
     74     }
     75     while(dfn[u] < dfn[v])
     76     {
     77 
     78        if(bridge[v])
     79        {
     80            cut--;
     81            bridge[v] = false;
     82        }
     83         v = pre[v];
     84     }
     85 }
     86 int main()
     87 {
     88     int n,m;
     89     int u,v;
     90     int tcase = 1;
     91     while(scanf("%d%d",&n,&m),n+m)
     92     {
     93         init(n);
     94         for(int i=1;i<=m;++i)
     95         {
     96             scanf("%d%d",&u,&v);
     97             addEdge(u,v);addEdge(v,u);
     98         }
     99         printf("Case %d:
    ",tcase++);
    100         tarjan(1,-1);
    101         int q;
    102         scanf("%d",&q);
    103         while(q--)
    104         {
    105             scanf("%d%d",&u,&v);
    106             lca(u,v);
    107             printf("%d
    ",cut);
    108         }
    109         puts("");
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    NC_6_TREE_MAX_PATH
    NC_12_reConstructBinaryTree
    NC_15_levelOrder
    NC_7_MAXPROFIT
    NC_9_HAS_PATH_SUM
    NC_8_BINARYTREE_SUMPATH
    NC_13_MAX_DEPTH
    IDEA的基本使用:让你的IDEA有飞一般的感觉
    Java获取当前系统事件System.currentTimeMillis()方法 ,获取当前时间戳10位 1665291145 转为时间字符串 yyyMMdd
    JAVA中计算两个日期时间的差值竟然也有这么多门道
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4794840.html
Copyright © 2020-2023  润新知