zoukankan      html  css  js  c++  java
  • FZU2259 : 图

    假设删除的边是$(u,v)$,分两种情况讨论:

    $1.$删除$(u,v)$之后$(u,v)$不再连通,那么说明$(u,v)$是图的桥,同时整个图都要是二分图。

    $2.$删除$(u,v)$之后$(u,v)$依然连通,那么图不能是二分图,但是删除$(u,v)$之后必须要是二分图,这说明$(u,v)$位于所有奇环的交上,在忽略这条边之后可以进行黑白染色,且$u,v$必定同色。对图求出dfs生成树,找出所有基环,对每条边标记它被多少个奇数长度的基环与多少个偶数长度的基环经过。如果一条边被所有奇数长度的基环经过,且不被任何一个偶数长度的基环经过,那么就可行。

    时间复杂度$O(n+m)$。

    #include<cstdio>
    const int N=200010;
    int n,m,i,x,y,dep[N],g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,d[N],dfn,f[N];
    int cnt,loop,tag0[N],tag1[N],h0[N],h1[N],ans;
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    void dfs(int x){
      d[x]=++dfn;
      for(int i=g[x];i;i=nxt[i])if(w[i]!=f[x]){
        int y=v[i];
        if(d[y]&&d[y]<=d[x]){
          if(dep[x]^dep[y]){
            tag0[y]--;
            tag0[x]++;
            h0[w[i]]=1;
          }else{
            if(x==y)loop++;else cnt++;
            tag1[y]--;
            tag1[x]++;
            h1[w[i]]=1;
          }
        }else if(!d[y])f[y]=w[i],dep[y]=dep[x]^1,dfs(y);
      }
    }
    void cal(int x){
      for(int i=g[x];i;i=nxt[i])if(f[v[i]]==w[i]&&d[v[i]]>d[x])cal(v[i]),tag0[x]+=tag0[v[i]],tag1[x]+=tag1[v[i]];
      h0[f[x]]=tag0[x],h1[f[x]]=tag1[x];
    }
    namespace BCC{
    int cut[N],g[N],v[N<<1],nxt[N<<1],ed;
    int f[N],dfn[N],low[N],num;
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    void tarjan(int x){
      dfn[x]=low[x]=++num;
      for(int i=g[x];i;i=nxt[i])if(!dfn[v[i]]){
        f[v[i]]=i>>1,tarjan(v[i]);
        if(low[x]>low[v[i]])low[x]=low[v[i]];
      }else if(f[x]!=(i>>1)&&low[x]>dfn[v[i]])low[x]=dfn[v[i]];
      if(f[x]&&low[x]==dfn[x])cut[f[x]]=1;
    }
    }
    int main(){
      while(~scanf("%d%d",&n,&m)){
        for(BCC::ed=i=1;i<=m;i++){
          scanf("%d%d",&x,&y);
          add(x,y,i),add(y,x,i);
          BCC::add(x,y),BCC::add(y,x);
        }
        for(i=1;i<=n;i++)if(!d[i])dfs(i),cal(i);
        cnt+=loop/2;
        if(!cnt){
          for(i=1;i<=n;i++)if(!BCC::dfn[i])BCC::tarjan(i);
          for(i=1;i<=m;i++)if(BCC::cut[i])ans++;
        }else{
          for(i=1;i<=m;i++)if(h1[i]==cnt&&!h0[i])ans++;
        }
        printf("%d
    ",ans);
        ed=dfn=cnt=loop=ans=0;
        for(i=0;i<=n;i++)dep[i]=g[i]=d[i]=f[i]=tag0[i]=tag1[i]=0;
        for(i=0;i<=m;i++)h0[i]=h1[i]=0;
        for(i=0;i<=m;i++)BCC::cut[i]=0;
        for(i=0;i<=n;i++)BCC::g[i]=BCC::f[i]=BCC::dfn[i]=BCC::low[i]=0;
        BCC::num=0;
      }
    }
    

      

  • 相关阅读:
    Java实现 蓝桥杯 算法提高 扶老奶奶过街
    Java实现 蓝桥杯 算法提高 扶老奶奶过街
    RichEdit选中文字右键菜单的实现
    避免用户重复点击按钮(使用Enable:=False,消息繁忙时会有堵塞的问题,只能改用Sleep)
    枚举当前系统用户(使用NetUserEnum API枚举)
    通过Graphics对象获取它所属的Control
    Delphi中动态调用TXMLDocument的经历
    MongoDB集群
    瀑布流特效
    常用优化策略
  • 原文地址:https://www.cnblogs.com/clrs97/p/7182408.html
Copyright © 2011-2022 走看看