• CodeChef GRAPHCNT


    题目大意:

      一张n个点m条边的有向图,问有多少对(x,y)存在有一条从1到x的路径,有一条1到y的路径,他们俩不相交。

    题解:

      ……于是为了这题我去学习了一下支配树,感觉很妙啊。

      设定了一个起点之后,u支配点就是从起点到u的必经点。支配树就是每个点都向自己最近的支配点连边,这有一个线性算法……这篇博客 还不错。

      求出支配树之后就是一个问树上多少点对lca是1……嗯也挺难的对吧……

      贴个代码吧。

     1 program j01;
     2 const maxn=1000086;maxm=20000086;
     3 var q,next:array[0..maxm]of longint;
     4     head,pre,dom:array[0..maxn]of longint;
     5     semi,idom:array[0..maxn]of longint;
     6     f,fa,best:array[0..maxn]of longint;
     7     dfn,id:array[0..maxn]of longint;
     8     ans:int64;
     9     size:array[0..maxn]of longint;
    10     tt,n,m,i,u,v,tot:longint;
    11 
    12 procedure addd(var h:longint;v:longint);
    13 begin
    14     inc(tt);q[tt]:=v;next[tt]:=h;h:=tt;
    15 end;
    16 
    17 procedure dfs(i:longint);
    18 var j:longint;
    19 begin
    20     inc(tot);dfn[i]:=tot;id[tot]:=i;j:=head[i];
    21     while j>0 do
    22     begin
    23         if dfn[q[j]]=0 then begin fa[q[j]]:=i;dfs(q[j]);end;j:=next[j];
    24     end;
    25 end;
    26 
    27 function find(i:longint):longint;
    28 var v:longint;
    29 begin
    30     if f[i]=i then exit(i);
    31     v:=find(f[i]);
    32     if dfn[semi[best[f[i]]]]<dfn[semi[best[i]]] then best[i]:=best[f[i]];
    33     f[i]:=v;exit(v);
    34 end;
    35 
    36 procedure tarjan;
    37 var u,j:longint;
    38 begin
    39     for i:=tot downto 2 do
    40     begin
    41         u:=id[i];j:=pre[u];
    42         while j>0 do
    43         begin 
    44             if dfn[q[j]]=0 then begin j:=next[j];continue;end;
    45             find(q[j]);
    46             if dfn[semi[best[q[j]]]]<dfn[semi[u]] then semi[u]:=semi[best[q[j]]];
    47             j:=next[j];
    48         end;
    49         addd(dom[semi[u]],u);
    50         f[u]:=fa[u];u:=id[i-1];j:=dom[u];
    51         while j>0 do
    52         begin
    53             find(q[j]);
    54             if semi[best[q[j]]]=u then idom[q[j]]:=u
    55                 else idom[q[j]]:=best[q[j]];
    56             j:=next[j];
    57         end;
    58     end;
    59     for i:=2 to tot do
    60     begin
    61         u:=id[i];if idom[u]<>semi[u] then idom[u]:=idom[idom[u]];
    62     end;
    63 end;
    64 
    65 begin
    66     readln(n,m);
    67     for i:=1 to m do
    68     begin
    69         readln(u,v);addd(head[u],v);addd(pre[v],u);
    70     end;
    71     dfs(1);
    72     for i:=1 to n do
    73     begin
    74         f[i]:=i;semi[i]:=i;best[i]:=i;
    75     end;
    76     tarjan;
    77     ans:=int64(tot)*(tot-1)div 2;
    78     for i:=tot downto 2 do
    79     begin
    80         u:=id[i];inc(size[u]);
    81         if idom[u]=1 then ans:=ans-(int64(size[u])*(size[u]-1)div 2);
    82         inc(size[idom[u]],size[u]);
    83     end;
    84     writeln(ans);
    85     //for i:=1 to n do writeln(i,':',idom[i]);
    86 end.
    View Code
  • 相关阅读:
    枚举
    枚举
    比特币中的密码学原理
    贪心
    dp
    二分
    mac解决matplotlib中文乱码
    Keras使用多个GPU并行
    pyspark使用-dataframe操作
    箱线图
  • 原文地址:https://www.cnblogs.com/oldjang/p/6920982.html
Copyright © 2020-2023  润新知