• 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;
      }
    }
    

      

  • 相关阅读:
    java23种设计模式(四)-- 桥接模式
    java23种设计模式(三)-- 适配器模式
    elasticsearch 进行聚合+去重查询
    postgresql绿色版安装及Navicat创建数据库,导入导出sql
    java的序列化
    常用正则表达式公式总结
    spring事务管理
    用私有构造器或者枚举类型强化SingleTon(单例)属性
    Spark集群运行与优化
    Hive优化
  • 原文地址:https://www.cnblogs.com/clrs97/p/7182408.html
Copyright © 2020-2023  润新知