倍增lca ZJOI2012 災難

2022-05-06 16:36:11 字數 3730 閱讀 2093

乙個食物網有n個點,代表n種生物,如果生物x可以吃生物y,那麼從y向x連乙個有向邊。這個圖沒有環。圖中有一些點沒有連出邊,這些點代表的生物都是生產者,可以通過光合作用來生存; 而有連出邊的點代表的都是消費者,它們必須通過吃其他生物來生存。如果某個消費者的所有食物都滅絕了,它會跟著滅絕。我們定義乙個生物在食物網中的「災難值」為,如果它突然滅絕,那麼會跟著一起滅絕的生物的種數。現在請你求出每乙個物種的「災難值」。

首先思考:什麼情況下乙個物種會滅絕?也就是所有它能吃的東西滅絕了,它就滅絕了。所以如果要讓物種a滅絕,我們可以選乙個物種b,使得物種a所有能吃的東西都滅絕。我們定義」滅絕樹」,其中乙個節點的父親是能讓它滅絕的深度最低的結點。不難發現滅絕樹上a的祖先滅絕後,a一定滅絕。所以若要讓物種x,y一起滅絕,只需查詢它們所有父親在滅絕樹上的lca即可。

這道題做了三天。。最後用cyaron對拍出來,發現是乙個以前寫的模組忘記改回來了。。以後寫程式就要一口氣寫完,不要被外界干擾。

1 #include 2 #include 3 #include 4 #include 5

using

namespace

std;67

const

int maxn=1000000;8

9int first1[maxn], first2[maxn], topo[maxn], topo2[maxn], out

[maxn];

10int fa[maxn][30

], dep[maxn], size[maxn], ans[maxn];

11struct

edge;

14edge edges1[maxn], edges2[maxn];

1516

intn, cnte1, cnte2;

1718

void addedge(int *first, edge *edges, int &cntedge,

19int v, int

from, int

to)27

28double log2(int

x)31

32int get_lca(int x, int

y)41

for (int step=20; step>0; --step)46}

47if (x!=y) x=fa[x][1

];48

return

x;49}50

51int

main()63}

64 queueq;

65for (int i=1; i<=n; ++i)71}

72//

以上:讀入、加邊

73 q.push(0

);74

intnownode, nowedge, nowson;

75for (int i=0; i<=n; ++i)

85 nowedge=edges2[nowedge].next;86}

87}88//

以上:拓撲排序

89int lca=0, cur=0;90

for (int i=1; i<=n; ++i)

101 dep[nownode]=dep[lca]+1

;102 cur=0

;103 fa[nownode][cur]=nownode;

104 fa[nownode][++cur]=lca;

105 ++size[lca];

106while

(fa[nownode][cur])

110}

111//

以上:建立滅絕樹

112while (!q.empty()) q.pop();

113for (int i=0; i<=n; ++i)

117int

fath;

118for (int i=n; i>0; --i)

126//

以上:統計size

127for (int i=1; i<=n; ++i)

128 printf("

%d\n

", ans[i]-1

);129

return0;

130 }

附:用來對拍的python程式。

1

from cyaron import *

2from random import

randint34

for n in range(5, 11):

5 input_io =io()

6for i in range(0, 100):7#

對於n,生成100個資料。

8input_io.input_writeln(n)

9print(n) #

##10 topo = vector.random(n, [(1, n)], 0)

11for j in

topo:

12print(j, end='

') #

##13

#拓撲序

14print() #

##15 m = randint(n*2, n*3)16#

有多少個邊(有一些邊會被捨棄掉)

17 out =

18for j in

range(0, n):

1920

#每個結點的出度(吃什麼)

21for j in

range(0, m):

22 t = randint(0, n-1)

23if out[t] < t / 2:

24 out[t] += 1

25 graph =

26for j in

range(0, n):

2728

for j in range(1, n):29#

對於每乙個結點

30 use =31#

連了哪些結點

32for k in

range(0, n):

3334

for k in

range(0, out[j]):35#

對於要連的邊

36 node = randint(0, j-1)

37while use[node] == 1:

38 node = randint(0, j-1)

39 use[node] = 140#

選乙個點

42for j in

graph:

43for k in

j:44

#print(k, end=" ")

45input_io.input_write(k)46#

print(0)

47input_io.input_writeln(0)

48 compare.program("

mine.exe

", input=input_io,

49 std_program="

yangs.exe

", stop_on_incorrect=true)

NOIP2012 開車旅行 (倍增)

小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj 旅行過程中...

JLOI 2012 樹(樹上倍增)

傳送門 solution 考慮倍增,維護up和w陣列,up i j 代表i節點向上跳2 j能到達的節點,w i j 代表i節點及其以上2 j的和,一遍dfs,常規倍增處理即可。特別地,w i 0 的值不是val father 而是val i include define n 100005 using...

NOIP2012開車旅行 倍增

小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj 旅行過程中...