支配树

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\n",ret);
  }

 

 
posted @ 2017-12-24 13:40  z1j1n1  阅读(218)  评论(0编辑  收藏  举报