乙個食物網有n個點,代表n種生物,如果生物x可以吃生物y,那麼從y向x連乙個有向邊。這個圖沒有環。圖中有一些點沒有連出邊,這些點代表的生物都是生產者,可以通過光合作用來生存; 而有連出邊的點代表的都是消費者,它們必須通過吃其他生物來生存。如果某個消費者的所有食物都滅絕了,它會跟著滅絕。我們定義乙個生物在食物網中的「災難值」為,如果它突然滅絕,那麼會跟著一起滅絕的生物的種數。現在請你求出每乙個物種的「災難值」。首先思考:什麼情況下乙個物種會滅絕?也就是所有它能吃的東西滅絕了,它就滅絕了。所以如果要讓物種a滅絕,我們可以選乙個物種b,使得物種a所有能吃的東西都滅絕。我們定義」滅絕樹」,其中乙個節點的父親是能讓它滅絕的深度最低的結點。不難發現滅絕樹上a的祖先滅絕後,a一定滅絕。所以若要讓物種x,y一起滅絕,只需查詢它們所有父親在滅絕樹上的lca即可。
這道題做了三天。。最後用cyaron對拍出來,發現是乙個以前寫的模組忘記改回來了。。以後寫程式就要一口氣寫完,不要被外界干擾。
1 #include 2 #include 3 #include 4 #include 5using
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程式。
1from 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 旅行過程中...