codevs P1421 秋靜葉 秋穣子

2021-08-14 16:45:20 字數 2342 閱讀 8634

在幻想鄉,秋姐妹決定比比誰能夠收集到最多的紅葉。靜葉將紅葉分成了n堆(編號1..n),並且規定了它們的選取順序,剛好形成一顆有向樹。在遊戲過程中,兩人從根節點開始,輪流取走紅葉,當乙個人取走節點i的紅葉後,另乙個人只能從節點i的兒子節點中選取乙個。當取到某個葉子時遊戲結束,然後兩人會比較自己得到的紅葉數量。已知兩人採用的策略不一樣,靜葉考慮在讓穰子取得盡可能少的前提下,自己取的最多;而穰子想得是在自己盡可能取得多的前提下,讓靜葉取得最少。在兩人都採取最優策略的情況下,請你計算出遊戲結束時兩人的紅葉數量。

遊戲總是靜葉先取,保證只存在一組解。

資料範圍

對於30%的資料:1 ≤ n ≤ 100,1 ≤ num[i] ≤ 100

對於60%的資料:1 ≤ n ≤ 10,000,1 ≤ num[i] ≤ 10,000

對於100%的資料:1 ≤ n ≤ 100,000,1 ≤ num[i] ≤ 10,000

注意:

保證兩人得到的紅葉數在[0, 2^31-1]。

樹上dp+博弈:

設f[i][0]表示以i為根的子樹先手最優值,f[i][1]相應表示後手最優值,注意這裡是先手跟後手,不是固定的靜葉跟穰子。

當靜葉是先手,穰子是後手,兒子為k:

你要使得f[k,0]最小的時候f[k,1]最大

f[i][0]=f[k][1]+num[i]

當穰子是先手,靜葉是後手,兒子為k:

你要使得f[k,1]最大的時候f[k,0]最小

f[i][0]=f[k][1]+num[i]

這樣的dp其實很容易實現,

雖然直接dfs可能會炸,但手工棧或從葉子節點逆著廣搜推子節點就可以了。

codevs dfs竟然過了。。

var

next,list,a,x,y:array [0..100001] of longint;

f:array [0..100001,0..1] of longint;

b:array [0..100001] of boolean;

i,j,k,n,m:longint;

function

max(aa,bb:longint):longint;

begin

if aa>bb then

exit(aa);

exit(bb);

end;

procedure

dfs(dep,rp:longint);

var i,j,k,op,cp:longint;

begin

cp:=maxlongint;

op:=0;

k:=0;

if dep=1

then

begin

j:=list[rp];

while j>0

dobegin

dfs(0,y[j]);

if (f[y[j],0]>op) or ((f[y[j],0]=op) and (f[y[j],1]then

begin

op:=f[y[j],0];

cp:=f[y[j],1];

k:=y[j];

end;

j:=next[j];

end;

endelse

begin

j:=list[rp];

while j>0

dobegin

dfs(1,y[j]);

if (f[y[j],1]or ((f[y[j],1]=cp) and (f[y[j],0]>op))

then

begin

op:=f[y[j],0];

cp:=f[y[j],1];

k:=y[j];

end;

j:=next[j];

end;

end;

f[rp,0]:=f[k,1]+a[rp];

f[rp,1]:=f[k,0];

end;

begin

readln(n);

for i:=1

to n do

read(a[i]);

for i:=1

to n-1

dobegin

readln(x[i],y[i]);

next[i]:=list[x[i]];

list[x[i]]:=i;

b[y[i]]:=true;

end;

for i:=1

to n do

ifnot(b[i]) then k:=i;

dfs(1,k);

writeln(f[k,0],' ',f[k,1]);

end.

Codevs P3641 上帝選人

世界上的人都有智商iq和情商eq。我們用兩個數字來表示人的智商和情商,數字大就代表其相應智商或情商高。現在你面前有n個人,這n個人的智商和情商均已知,請你選擇出盡量多的人,要求選出的人中不存在任意兩人i和j,i的智商大於j的智商但i的情商小於j的情商。第一行乙個正整數n,表示人的數量。第二行至第n ...

CodeVS P2963 卡片整理

題目描述 description 小明有n張卡片,每張卡片都有乙個編號ai ai 0 但是這n張卡片中有一些編號是重複的,他想把重複的只留下一張,其餘的扔掉,統計出剩下的卡片數,並且把它們按編號從小到大排好,但卡片數量不少,比較繁瑣,想請你幫忙用程式設計來解決問題。輸入描述 input descri...

Codevs P1017 乘積最大

p1017 乘積最大 題目描述 description 今年是國際數學聯盟確定的 2000 世界數學年 又恰逢我國著名數學家華羅庚先生誕辰90周年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的乙個好朋友xz也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目...