• BZOJ2861 : 双向边定向为单向边


    将每条双向边拆成两条单向边,若两条边中至少存在一条边使得删掉它之后图中SCC个数不变,则这条边可以定向。

    将边中间加上点,变成删点问题。

    对于每个SCC单独考虑,随便选择一个不是拆点出来的点S作为源。

    则在正图或者反图的Dominator Tree上的所有非叶子节点均会影响连通性。

    用Lengauer-Tarjan算法求出Dominator Tree即可。

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

    #include<cstdio>
    const int N=500010,M=800010;
    int n,m,lim,i,x,y,z,ans;bool vis[N],cut[N];
    int g0[N],g1[N],v[M*2],nxt[M*2],ed,f[N],q[N],t,size,now[N],rk[N];
    namespace DT{
    int n,g1[N],g2[N],gd[N],v[M*3+N],nxt[M*3+N],ed;
    int cnt,dfn[N],id[N],fa[N],f[N],mn[N],sd[N],idom[N];
    inline void add(int*g,int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline void add(int x,int y){add(g1,x,y);add(g2,y,x);}
    int F(int x){
      if(f[x]==x)return x;
      int y=F(f[x]);
      if(sd[mn[x]]>sd[mn[f[x]]])mn[x]=mn[f[x]];
      return f[x]=y;
    }
    void dfs(int x){
      id[dfn[x]=++cnt]=x;
      for(int i=g1[x];i;i=nxt[i])if(!dfn[v[i]])dfs(v[i]),fa[dfn[v[i]]]=dfn[x];
    }
    inline void tarjan(int S){
      int i,j,k,x;
      for(cnt=0,i=1;i<=n;i++)gd[i]=dfn[i]=id[i]=fa[i]=idom[i]=0,f[i]=sd[i]=mn[i]=i;
      dfs(S);
      for(i=n;i>1;i--){
        for(j=g2[id[i]];j;j=nxt[j])F(k=dfn[v[j]]),sd[i]=sd[i]<sd[mn[k]]?sd[i]:sd[mn[k]];
        add(gd,sd[i],i);
        for(j=gd[f[i]=x=fa[i]];j;j=nxt[j])F(k=v[j]),idom[k]=sd[mn[k]]<x?mn[k]:x;
        gd[x]=0;
      }
      for(i=2;i<=n;add(gd,idom[i],i),i++)if(idom[i]!=sd[i])idom[i]=idom[idom[i]];
    }
    inline void init(int _n){
      n=_n;ed=0;
      for(int i=1;i<=n;i++)g1[i]=g2[i]=0;
    }
    }
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y){
      v[++ed]=y;nxt[ed]=g0[x];g0[x]=ed;
      v[++ed]=x;nxt[ed]=g1[y];g1[y]=ed;
    }
    void dfs1(int x){
      vis[x]=1;
      for(int i=g0[x];i;i=nxt[i])if(!vis[v[i]])dfs1(v[i]);
      q[++t]=x;
    }
    void dfs2(int x,int y){
      vis[x]=0,f[x]=y;
      now[rk[x]=++size]=x;
      for(int i=g1[x];i;i=nxt[i])if(vis[v[i]])dfs2(v[i],y);
    }
    inline void solve(int o){
      int i,j;
      for(i=1;i<=size;i++)if(now[i]>lim)break;
      if(i>size)return;
      DT::init(size);
      for(i=1;i<=size;i++)for(j=g0[now[i]];j;j=nxt[j])if(f[v[j]]==o)DT::add(i,rk[v[j]]);
      for(i=1;i<=size;i++)if(now[i]<=lim){
        DT::tarjan(i);
        break;
      }
      for(i=1;i<=size;i++)if(DT::gd[DT::dfn[i]])cut[now[i]]=1;
      DT::init(size);
      for(i=1;i<=size;i++)for(j=g0[now[i]];j;j=nxt[j])if(f[v[j]]==o)DT::add(rk[v[j]],i);
      for(i=1;i<=size;i++)if(now[i]<=lim){
        DT::tarjan(i);
        break;
      }
      for(i=1;i<=size;i++)if(DT::gd[DT::dfn[i]])cut[now[i]]=1;
    }
    int main(){
      read(n),read(m);lim=n;
      while(m--){
        read(x),read(y),read(z);
        if(x==y){ans+=z==2;continue;}
        if(z==1)add(x,y);
        else{
          add(x,++n);
          add(n,y);
          add(y,++n);
          add(n,x);
        }
      }
      for(i=1;i<=n;i++)if(!vis[i])dfs1(i);
      for(i=n;i;i--)if(vis[q[i]]){
        size=0;
        dfs2(q[i],q[i]);
        solve(q[i]);
      }
      for(i=lim+1;i<=n;i+=2)if(!cut[i]||!cut[i+1])ans++;
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    [转]对Lucene PhraseQuery的slop的理解
    Best jQuery Plugins of 2010
    15 jQuery Plugins To Create A User Friendly Tooltip
    Lucene:基于Java的全文检索引擎简介
    9 Powerful jQuery File Upload Plugins
    Coding Best Practices Using DateTime in the .NET Framework
    Best Image Croppers ready to use for web developers
    28 jQuery Zoom Plugins Creating Stunning Image Effect
    VS2005 + VSS2005 实现团队开发、源代码管理、版本控制(转)
    禁止状态栏显示超链
  • 原文地址:https://www.cnblogs.com/clrs97/p/6361299.html
Copyright © 2020-2023  润新知