zoukankan      html  css  js  c++  java
  • 支配树

    CODECHEF MAY15 GRAPHCNT

    求sdom

       sdom[u]=fa[u]

     dfn[v]>dfn[u] 即(v->u)为横插边或反组边 则有sdom[u]=Min(sdom[u],sdom[x]),x为v到根的路径节点中已连通点中sdom最小的节点

    求idom 

    sdom[u]>=sdom[x] idom[x]=sdom[x]
    sdom[u]< sdom[x] idom[x]=idom[u],u为sdom最小的点
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
      int bt[600001],dfn[600001],cnt,lis[600001],nd[600001],nxt[600001],des[600001],fat[600001];
      int fa[600001],mins[600001],minpo[600001],n,m,sdom[600001],idom[600001];
      long long size[600001];
      vector <int> que[600001];
     
      struct data{
        int x,y;
      }sid[600001];
      
      struct data2{
        int x,y,z;
      };
    
      void addedge(int x,int y){
          nxt[++cnt]=nd[x];des[cnt]=y;nd[x]=cnt;
      }
    
      void dfs(int po){
        bt[po]=1;dfn[po]=++cnt;lis[cnt]=po;
        for (int p=nd[po];p!=-1;p=nxt[p])
          if (!bt[des[p]]){
              dfs(des[p]);
              fat[des[p]]=po;
          }
      }
    
      int mycomp(const data a,const data b){
          return(dfn[a.y]>dfn[b.y]);
      }
    
      data2 find(int po){
          if (fa[po]==po) return((data2){po,mins[po],minpo[po]});
          data2 t=find(fa[po]);
          if (dfn[mins[po]]<dfn[t.y]){
            t.y=mins[po];t.z=minpo[po];
        }else
        if (dfn[mins[po]]>dfn[t.y]){
          mins[po]=t.y;minpo[po]=t.z;
        }
        fa[po]=t.x;
        return(t);
      }
    
      int main(){      
          scanf("%d%d",&n,&m);
          for (int i=1;i<=n;i++) nd[i]=-1;
          for (int i=1;i<=m;i++){
            scanf("%d%d",&sid[i].x,&sid[i].y);
          addedge(sid[i].x,sid[i].y);    
        }
        cnt=0;
        dfs(1);
        
        for (int i=1;i<=n;i++) fa[i]=i,mins[i]=n+1;
        for (int i=1;i<=cnt;i++) mins[lis[i]]=lis[i],minpo[lis[i]]=lis[i];
        dfn[n+1]=1e9;idom[1]=1;
        sort(sid+1,sid+m+1,mycomp);
        int po=1;
        for (int i=cnt;i>=1;i--){
          while (que[lis[i]].size()){
              int t=que[lis[i]][que[lis[i]].size()-1];que[lis[i]].pop_back();
              data2 fin=find(t);
              if (dfn[fin.y]>=dfn[sdom[t]]) idom[t]=sdom[t];else
                idom[t]=-fin.z;
          }
          
          int mini=n+1,mipo;
          while (po<=m&&sid[po].y==lis[i]){
              data2 fin=find(sid[po].x);
              if (dfn[fin.y]<dfn[mini]) mini=fin.y;    
              po++;
          }
          sdom[lis[i]]=mins[lis[i]]=mini;
          
          que[sdom[lis[i]]].push_back(lis[i]);
          for (int p=nd[lis[i]];p!=-1;p=nxt[p])
            if (fat[des[p]]==lis[i])
              fa[des[p]]=lis[i];
        }
        for (int i=1;i<=cnt;i++)
          if (idom[lis[i]]<0)
            idom[lis[i]]=idom[-idom[lis[i]]];
        
        long long ret=(long long)cnt*(cnt-1)/2;
        for (int i=1;i<=cnt;i++) size[lis[i]]=1;
        for (int i=cnt;i>1;i--){
          if (idom[lis[i]]!=1) ret-=size[idom[lis[i]]]*size[lis[i]];
          size[idom[lis[i]]]+=size[lis[i]];
        }
        printf("%lld
    ",ret);
      }
    
    
    
     
  • 相关阅读:
    C语言面试题大汇总
    cocos2d-x的win32编译环境
    完美解决Android SDK Manager无法更新
    ADT离线安装教程
    Android开发环境搭建教程
    如何利用dex2jar反编译APK
    Eclipse与Android源码中ProGuard工具的使用
    Proguard语法及常用proguard.cfg代码段
    Android之ProGuard混淆器
    Nutch源码阅读进程2---Generate
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/8097902.html
Copyright © 2011-2022 走看看