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.

时间: 2024-08-23 12:37:01

CodeChef GRAPHCNT的相关文章

支配树学习笔记

支配树(dominator tree) 学习笔记 学习背景 本来本蒟蒻都不知道有一个东西叫支配树……pkuwc前查某位的水表看见它的大名,甚感恐慌啊.不过好在pkuwc5道题(嗯?)都是概率期望计数,也不知是好还是不好,我在这些方面也只是不好不差……扯远了. 考挂之后也没什么心思干别的,想起支配树这个东西,于是打算学一下. 技能介绍(雾) 支配树是什么?不如直接讲支配树的性质,从性质分析它的定义. 先大概讲一下它是来求什么的. 问题:我们有一个有向图(可以有环),定下了一个节点为起点s.现在我们

CodeChef Counting on a directed graph

Counting on a directed graph Problem Code: GRAPHCNT All submissions for this problem are available. Read problems statements in Mandarin Chineseand Russian. Given an directed graph with N nodes (numbered from 1 to N) and M edges, calculate the number

CodeChef FNCS (分块+树状数组)

题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, r] 的函数和,那么我们可以用 sum[r] - sum[l-1] 来求得. 由于这个数据量有点大,所以我们将函数分块. 例如样例: 1 3 有5个函数,那么我们分成3块.{ [1 3] , [2 5] }, { [4 5], [3 5] }, { [1 2] }.每一块对应都有一个sum ,这时如

codechef营养题 第三弹

第三弾が始まる! codechef problems 第三弹 一.Motorbike Racing 题面 It's time for the annual exciting Motorbike Race in Byteland. There are N motorcyclists taking part in the competition. Johnny is watching the race. At the present moment (time 0), Johnny has taken

codechef 营养题 第一弹

第一弾が始まる! 定期更新しない! 来源:http://wenku.baidu.com/link?url=XOJLwfgMsZp_9nhAK15591XFRgZl7f7_x7wtZ5_3T2peHh5XXoERDanUcdxw08SmRj1a5VY1o7jpW1xYv_V1kuYao1Pg4yKdfG4MfNsNAEa codechef problems 第一弹 一.Authentication Failed原题题面Several days ago Chef decided to registe

bzoj4260: Codechef REBXOR

求异或maxmin一般用trie (二进制式的trie).query中找的是满足((x>>i)&1)^A=1,那么A=((x>>i)&1)^1:maxx=max(sumx,sumi)(i=[1,x]).(YY一下异或的性质 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #def

Codechef July Challenge 2014部分题解

Dish Owner(并查集) 链接:http://www.codechef.com/JULY14/problems/DISHOWN/ 题意分析:本题主要操作就是给出0 x y时,拥有第x道菜的厨师与拥有第y道菜的厨师pk,谁拥有的所有菜的其中一道菜(不一定是x或y)的分值比较高谁就获胜,并赢得loser的所有菜.即比较的是每个人分值最高的菜,所以对于非loser的人来说,他的分值最高的菜是不变的.综合题意用并查集易解. #include <cstdio> const int Maxn=100

codechef Row and Column Operations 题解

You are given an N × N grid initially filled by zeros. Let the rows and columns of the grid be numbered from1 to N, inclusive. There are two types of operations can be applied to the grid: RowAdd R X: all numbers in the row R should be increased by X

Codechef Nuclear Reactors 题解

There are K nuclear reactor chambers labelled from 0 to K-1. Particles are bombarded onto chamber 0. The particles keep collecting in the chamber 0. However if at any time, there are more than N particles in a chamber, a reaction will cause 1 particl