zoukankan      html  css  js  c++  java
  • poj 3694 Network(割边+lca)

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

    题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目。

    分析:通常的做法是:先求出该无向图的桥的数目count和边双连通分量,缩点,每次加边(u,v),判断若u,v属于同一个双连通分量,则桥的数目不变,否则,桥的数目必定会减少,这时桥减少的数目明显和最近公共祖先lca有关,用裸的lca就行了,每次u和v向父节点回退,如果该节点是桥的端点,则count--,直到u==v为止。

    有个优化:其实不用缩点,只要在求出桥的时候标记一下,然后在用lca求减少桥的数目时,利用dfn[]就行了,因为u,v的最近公共祖先dfn[]一定相等。

    AC代码如下:

      1 #include<cstdio>
      2 #include<cstring>
      3 const int N=1000000+5;
      4 const int M=2000000+5;
      5 struct EDGE{
      6     int v,next;
      7 }edge[M];
      8 int first[N],dfn[N],low[N],bri[N],pre[N];
      9 int g,cnt,count;
     10 void AddEdge(int u,int v)
     11 {
     12     edge[g].v=v;
     13     edge[g].next=first[u];
     14     first[u]=g++;
     15 }
     16 int min(int a,int b)
     17 {
     18     return a<b?a:b;
     19 }
     20 void Tarjan(int u,int fa)
     21 {
     22     int i,v;
     23     low[u]=dfn[u]=++cnt;
     24     for(i=first[u];i!=-1;i=edge[i].next)
     25     {
     26         v=edge[i].v;
     27         if(i==(fa^1))
     28             continue;
     29         if(!dfn[v])
     30         {
     31             pre[v]=u;
     32             Tarjan(v,i);
     33             low[u]=min(low[u],low[v]);
     34             if(low[v]>dfn[u])
     35             {
     36                 count++;
     37                 bri[v]=1;
     38             }
     39         }
     40         else
     41             low[u]=min(low[u],dfn[v]);
     42     }
     43 }
     44 void lca(int u,int v)
     45 {
     46     while(dfn[u]>dfn[v])
     47     {
     48         if(bri[u])
     49         {
     50             count--;
     51             bri[u]=0;
     52         }
     53         u=pre[u];
     54     }
     55     while(dfn[v]>dfn[u])
     56     {
     57         if(bri[v])
     58         {
     59             count--;
     60             bri[v]=0;
     61         }
     62         v=pre[v];
     63     }
     64     while(u!=v)
     65     {
     66         if(bri[u])
     67         {
     68             count--;
     69             bri[u]=0;
     70         }
     71         if(bri[v])
     72         {
     73             count--;
     74             bri[v]=0;
     75         }
     76         u=pre[u];
     77         v=pre[v];
     78     }
     79 }
     80 int main()
     81 {
     82     int n,m,i,u,v,q;
     83     int cas=1;
     84     while(scanf("%d%d",&n,&m)!=EOF)
     85     {
     86         if(n==0&&m==0)
     87             break;
     88         g=cnt=count=0;
     89         memset(first,-1,sizeof(first));
     90         memset(dfn,0,sizeof(dfn));
     91         memset(bri,0,sizeof(bri));
     92         for(i=0;i<m;i++)
     93         {
     94             scanf("%d%d",&u,&v);
     95             AddEdge(u,v);
     96             AddEdge(v,u);
     97         }
     98         for(i=1;i<=n;i++)
     99             if(!dfn[i])
    100                 Tarjan(i,-1);
    101         scanf("%d",&q);
    102         printf("Case %d:
    ",cas++);
    103         for(i=0;i<q;i++)
    104         {
    105             scanf("%d%d",&u,&v);
    106             lca(u,v);
    107             printf("%d
    ",count);
    108         }
    109         printf("
    ");
    110     }
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    element-ui中tabs页设置第一个页面不可关闭
    验证实现element-ui树形控件的自定义图标及右键菜单
    vue项目接口地址的定义
    js数组与字符串的相互转换方法
    vue的双向绑定原理及实现
    vue中的懒加载和按需加载
    使用gulp将移动端px转为rem
    百度搜索--jquery
    关于Ajax中http协议
    用nodejs搭建一个简单的服务器
  • 原文地址:https://www.cnblogs.com/frog112111/p/3382108.html
Copyright © 2011-2022 走看看