51nod1673 樹有幾多愁(狀壓DP)

2021-08-09 17:22:50 字數 2305 閱讀 4370

傳送門

lyk有一棵樹,它想給這棵樹重標號。

重標號後,這棵樹的所有葉子節點的值為它到根的路徑上的編號最小的點的編號。

這棵樹的煩惱值為所有葉子節點的值的乘積。

lyk想讓這棵樹的煩惱值最大,你只需輸出最大煩惱值對1e9+7取模後的值就可以了。

注意一開始1號節點為根,重標號後這個節點仍然為根。:資料保證葉子節點個數<=20。

題解:狀壓dp。

首先想到對於每個葉子節點到根節點的鏈上的標號一定是單調遞增的(上面比下面優)。

同時,每個葉子節點到根節點未被標號的路徑會一次性被標號,也就是說只要確定了葉子節點的選擇順序,那麼整棵樹的標號也就確定,因為每次標號會將所有到根的路徑上未被標號的點給標號。

證明應該很明顯,因為是取到根節點的最小值,假設現在有兩條鏈,設給兩條鏈先後標號的兩個min值為mi

n1,m

in2 ,且mi

n1為較小值,那麼如果同時標號必然會是mi

n1,m

in3 ,且mi

n3≤m

in2 因為最小的值肯定不變,而同時標號會導致另一條鏈上的最小值變小。

有了以上的結論,再看看葉子節點的個數:20,如果有高超的暴力技巧直接dfs剪枝就過了,不過我還是說一下正解:狀壓dp。

首先要想到狀壓dp應該不難,因為資料範圍很明顯,主要是怎麼dp,很容易想到用dp

[i] 表示當前已染色葉子節點的狀態以及最優乘積。(注意,這裡因為有mod的存在,為了避免高精度,最好取對數存入另乙個陣列來比較大小)

怎麼狀態轉移?

加入乙個點j到i狀態中,增加的乘積是j標號的點中的最小值。如果能夠求出j對於i能新增加多少個點,以及i已經染色的點的個數,那麼就很簡單了,接下來我說說怎麼處理,不妨記其為di

s[j]

[i]和

cnt[

i]

首先,對於cn

t[i]

。若其只有乙個數,那麼就等於這個數到根節點的距離,否則,列舉任意在狀態i中的已經選擇的點j,cn

t[i]

就等於j 對狀態(i

⊕(1<)的距離加上cn

t[(i

⊕(1<)]

。這個明顯可以dp。

問題轉化為求di

s[j]

[i] 。這個值其實就是

j 到

i中已經染色的點的最小距離。可以o(

n)求,當然,這種做法很低效,因為

j 到狀態

i中的很多染色的點在狀態

i 的子狀態中已經列舉過了。只需列舉任意乙個在狀態

i中的點

o ,取mi

n就好了,這個問題也得到了線性做法。

#include

using

namespace

std;

int n;

namespace task1

}inline

int getfa(int now)

return t;

}inline

int calc()

return res;

}inline

void dfs2(int now)

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

}inline

void solve()

dfs(1,0);

dfs2(1);

cout

while(isdigit(ch))

return i*f;

}int sze[maxn];

inline

int dfs(int now,int f)

return sze;

}inline

void dfstop(int now,int f)

for(int e=last[now];e;e=nxt[e])

}inline

int getlca(int x,int y)

inline

long

long calcdis(int x,int y)

inline

void pre()

}}else}}

}}inline

void add(int x,int y)

inline

void solve()

pre();

dp[0]=0;ans[0]=1;

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

}dp[i]=mx;

}cout

51nod1673樹有幾多愁

題目描述 lyk有一棵樹,它想給這棵樹重標號。重標號後,這棵樹的所有葉子節點的值為它到根的路徑上的編號最小的點的編號。這棵樹的煩惱值為所有葉子節點的值的乘積。lyk想讓這棵樹的煩惱值最大,你只需輸出最大煩惱值對1e9 7取模後的值就可以了。注意一開始1號節點為根,重標號後這個節點仍然為根。updat...

51nod 1673 樹有幾多愁

lyk有一棵樹,它想給這棵樹重標號。重標號後,這棵樹的所有葉子節點的值為它到根的路徑上的編號最小的點的編號。這棵樹的煩惱值為所有葉子節點的值的乘積。lyk想讓這棵樹的煩惱值最大,你只需輸出最大煩惱值對1e9 7取模後的值就可以了。注意一開始1號節點為根,重標號後這個節點仍然為根。資料保證葉子節點個數...

51nod1462 樹據結構

給一顆以1為根的樹。每個點有兩個權值 vi,ti,一開始全部是零。q次操作 讀入o,u,d o 1 對u到根上所有點的vi d o 2 對u到根上所有點的ti vi d 最後,輸出每個點的ti值 n,q 100000 有50 的資料n,q 10000 注 所有數64位整數不會爆。我們考慮用樹剖來做這...