zoukankan      html  css  js  c++  java
  • POJ3694 Network 边双缩点+LCA+并查集

    辣鸡错误:把dfs和ldfs搞混。。。QAQ


    题意:给定一个无向图,然后查询q次,求每次查询就在图上增加一条边,求剩余割边的个数。

    先把边双缩点,然后预处理出LCA的倍增数组;

    然后加边时,从u往上跳,把所有u到LCA(u,v)路径上割边去掉,即 --ans;v同理;

    而向上跳的时候可以用并查集,把已经去掉的边,用路径压缩忽略掉,会往上跳的更快些。

    memset记得写全,不然。。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #define R register int
     6 const int N=100010;
     7 using namespace std;
     8 inline int g() {
     9     R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    10     do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    11 }
    12 int n,m,cc,cnt,num,dcc,T;
    13 int vr[N<<2],nxt[N<<2],fir[N],dfn[N],low[N],c[N],d[N],f[N][18],fa[N];
    14 bool bge[N<<2];
    15 inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    16 void tarjan(int u,int E) {
    17     dfn[u]=low[u]=++num;
    18     for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
    19         if(!dfn[v]) {
    20             tarjan(v,i);
    21             low[u]=min(low[u],low[v]);
    22             if(low[v]>dfn[u]) bge[i]=bge[i^1]=true;
    23         } else if(i!=(E^1))low[u]=min(low[u],low[v]);
    24     }
    25 }
    26 void dfs(int u) {
    27     c[u]=dcc;
    28     for(R i=fir[u];i;i=nxt[i]) if(!bge[i]&&!c[vr[i]]) dfs(vr[i]);
    29 }
    30 int ff[N],vv[N<<2],nn[N<<2],tc=1;
    31 inline void addc(int u,int v) {vv[++tc]=v,nn[tc]=ff[u],ff[u]=tc;}
    32 inline void solve() {
    33     for(R i=2;i<=cnt;++i) {
    34         R u=vr[i^1],v=vr[i];
    35         if(c[u]==c[v]) continue;
    36         addc(c[u],c[v]);
    37     }
    38 }
    39 void ldfs(int u) {
    40     for(R i=ff[u];i;i=nn[i]) { R v=vv[i];
    41         if(d[v]) continue;
    42         f[v][0]=u,d[v]=d[u]+1; R p=u;
    43         for(R j=0;f[p][j];++j) f[v][j+1]=f[p][j],p=f[p][j];
    44         ldfs(v);
    45     }
    46 }
    47 inline int lca(int u,int v) {
    48     if(d[u]<d[v]) swap(u,v); R lim=log2(d[u])+1;
    49     for(R i=lim;i>=0;--i) if(d[f[u][i]]>=d[v]) u=f[u][i];
    50     if(u==v) return u;
    51     for(R i=lim;i>=0;--i) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    52     return f[u][0];
    53 }
    54 int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);}
    55 signed main() {
    56     while(n=g(),m=g(),m||n) { cnt=1;tc=1;num=dcc=cc=0;
    57         memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(nxt,0,sizeof(nxt));memset(fir,0,sizeof(fir));
    58         memset(bge,false,sizeof(bge));memset(nn,0,sizeof(nn));memset(ff,0,sizeof(ff)); memset(c,0,sizeof(c));memset(f,0,sizeof(f));
    59         for(R i=1,u,v;i<=m;++i) u=g(),v=g(),add(u,v),add(v,u);
    60         for(R i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0);
    61         for(R i=1;i<=n;++i) if(!c[i]) ++dcc,dfs(i);
    62         for(R i=1;i<=n;++i) fa[i]=i;
    63         solve(); d[1]=1;ldfs(1); R q=g(),ans=dcc-1; 
    64         printf("Case %d:
    ",++T);
    65         while(q--) {
    66             R u=g(),v=g();
    67             u=c[u],v=c[v]; R L=lca(u,v); //cout<<L<<'
    ';
    68             u=getf(u),v=getf(v);
    69             while(d[u]>d[L]) fa[u]=f[u][0],--ans,u=getf(u);
    70             while(d[v]>d[L]) fa[v]=f[v][0],--ans,v=getf(v);
    71             printf("%d
    ",ans);        
    72         } putchar('
    ');
    73     }
    74 }

    2019.04.12

  • 相关阅读:
    开始用博客
    nginx 移动端和PC端相互访问
    call、apply、bind的区别
    获取两个日期之间的所有日期组合
    高频前端开发问题
    图片懒加载实现
    某某公司中级前端面试题
    flex 布局
    plupload.js+php批量上传文件到阿里云oss
    H5 iframe 高度-根据内容的高度自适应 / iframe高度适配
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10695766.html
Copyright © 2011-2022 走看看