• [hdu2460]network(依次连边并询问图中割边数量) tarjan边双联通分量+lca


    题意:

    给定一个n个点m条边的无向图,q个操作,每个操作给(x,y)连边并询问此时图中的割边有多少条。(连上的边会一直存在)

    n<=1e5,m<=2*10^5,q<=1e3,多组数据。

    题解:

    用tarjan求边双连通分量并缩点,缩点后组成一棵树,记录此时割边共有sum条。

    连接(x,y),设c[i]为缩点后i所在的新点(边双连通分量),则c[x]-->lca-->c[y]形成一个环,环上的所有边都不再是割边,走一遍并标记,如果遇到没标记过的就sum--。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 using namespace std;
      6 
      7 const int N=100010,M=200010,K=20;
      8 int n,m,al,bl,sum,num,sl,cnt;
      9 int afirst[N],bfirst[N],fa[N][K],dfn[N],low[N],is[N],c[N],s[N],dep[N];
     10 struct node{
     11     int x,y,tmp,next;
     12 }a[2*M],b[2*M];
     13 
     14 int minn(int x,int y){return x<y ? x:y;}
     15 
     16 void ins_a(int x,int y)
     17 {
     18     a[++al].x=x;a[al].y=y;a[al].tmp=0;
     19     a[al].next=afirst[x];afirst[x]=al;
     20 }
     21 
     22 void ins_b(int x,int y)
     23 {
     24     b[++bl].x=x;b[bl].y=y;
     25     b[bl].next=bfirst[x];bfirst[x]=bl;
     26 }
     27 
     28 void tarjan(int x)
     29 {
     30     dfn[x]=low[x]=++num;
     31     s[++sl]=x;
     32     for(int i=afirst[x];i;i=a[i].next)
     33     {
     34         if(a[i].tmp) continue;
     35         a[i].tmp=1;
     36         a[i%2==0 ? i-1:i+1].tmp=1;
     37         int y=a[i].y;
     38         if(!dfn[y])
     39         {
     40             tarjan(y);
     41             low[x]=minn(low[x],low[y]);
     42             if(dfn[x]<low[y])
     43             {
     44                 sum++;//printf("%d -- > %d
    ",x,y);
     45                 cnt++;
     46                 int z;
     47                 while(1)
     48                 {
     49                     z=s[sl--];
     50                     c[z]=cnt;
     51                     if(z==y) break;
     52                 }
     53             }
     54         }
     55         else low[x]=minn(low[x],dfn[y]);
     56     }
     57 }
     58 
     59 void dfs(int x)
     60 {
     61     for(int i=bfirst[x];i;i=b[i].next)
     62     {
     63         int y=b[i].y;
     64         if(y==fa[x][0]) continue;
     65         fa[y][0]=x;dep[y]=dep[x]+1;
     66         dfs(y);
     67     }
     68 }
     69 
     70 void prepare_lca()
     71 {
     72     memset(fa,0,sizeof(fa));
     73     memset(dep,0,sizeof(dep));
     74     memset(is,0,sizeof(is));
     75     dep[1]=1;
     76     dfs(1);
     77     for(int j=1;j<=18;j++)
     78         for(int i=1;i<=n;i++)
     79             fa[i][j]=fa[fa[i][j-1]][j-1];
     80 }
     81 
     82 int get_lca(int x,int y)
     83 {
     84     if(dep[x]<dep[y]) swap(x,y);
     85     for(int i=18;i>=0;i--)
     86         if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
     87     if(x==y) return x;
     88     for(int i=18;i>=0;i--)
     89     {
     90         if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
     91     }
     92     return fa[x][0];
     93 }
     94 
     95 void del(int x,int y,int lca)
     96 {
     97     while(x!=lca) 
     98     {
     99         if(!is[x]) sum--;
    100         is[x]=1;
    101         x=fa[x][0];
    102     }
    103     while(y!=lca)
    104     {
    105         if(!is[y]) sum--;
    106         is[y]=1;
    107         y=fa[y][0];
    108     }
    109 }
    110 
    111 int main()
    112 {
    113     freopen("a.in","r",stdin);
    114     int q,x,y,T=0;
    115     while(1)
    116     {
    117         scanf("%d%d",&n,&m);
    118         if(!n && !m) return 0;
    119         printf("Case %d:
    ",++T);
    120         al=0;bl=0;sum=0;
    121         memset(afirst,0,sizeof(afirst));
    122         memset(bfirst,0,sizeof(bfirst));
    123         num=0;sl=0;cnt=0;
    124         memset(dfn,0,sizeof(dfn));
    125         memset(c,0,sizeof(c));
    126         for(int i=1;i<=m;i++)
    127         {
    128             scanf("%d%d",&x,&y);
    129             ins_a(x,y);ins_a(y,x);
    130         }
    131         for(int i=1;i<=n;i++)
    132         {
    133             if(!dfn[i]) 
    134             {
    135                 tarjan(i);
    136                 if(sl) 
    137                 {
    138                     cnt++;
    139                     for(int i=1;i<=sl;i++) c[s[i]]=cnt;
    140                     sl=0;
    141                 }
    142             }
    143         }
    144             
    145         for(int i=1;i<=2*m;i++)
    146         {
    147             x=a[i].x,y=a[i].y;
    148             if(c[x]!=c[y]) ins_b(c[x],c[y]);
    149         }
    150         // for(int i=1;i<=bl;i++) 
    151             // printf("%d -- > %d
    ",b[i].x,b[i].y);
    152         // for(int i=1;i<=n;i++) printf("c [ %d ] = %d
    ",i,c[i]);
    153         prepare_lca();
    154         scanf("%d",&q);
    155         for(int i=1;i<=q;i++)
    156         {
    157             scanf("%d%d",&x,&y);
    158             x=c[x];y=c[y];
    159             int lca=get_lca(x,y);
    160             del(x,y,lca);
    161             printf("%d
    ",sum);
    162         }
    163         printf("
    ");
    164     }
    165     return 0;
    166 }
  • 相关阅读:
    同一账号在不同浏览器不能同时登录
    子页面像父页面传递参数--数组
    bootstaptable动态合并单元格和jxls动态合并单元格
    RedisTemplate的使用
    java项目中读取配置文件
    httpclient调用接口
    drop、truncate和delete的区别
    函数式编程
    常见配置redis.conf介绍
    mysql和redis加入到windows服务
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/9708552.html
Copyright © 2020-2023  润新知