BZOJ3162 獨釣寒江雪 樹同構 DP

2022-05-20 10:03:21 字數 1152 閱讀 5343

題解:先進行樹hash,方法是找重心,如果重心有兩個,則新建乙個虛點將兩個重心連起來,新點即為新樹的重心。將重心當做根進行hash,hash函式不能太簡單,我的方法是:將x的所有兒子的hash值排序,然後將這些hash值立方合在一起作為x的hash值。

進行完樹hash後,我們考慮dp。首先不考慮同構,設f[0/1][x]表示選(不選)x時,在x的子樹中選出獨立集的方案數,則有

$f[0][x]=\prod f[1][y]+f[0][y]\\f[1][x]=\prod f[0][y]$

考慮同構,如果x有m個兒子是相同的,它們的f值都是s,那麼可以轉化成如下問題:給m個相同球染s種顏色有多少種方案,顯然答案=$c_^m$。

如果根是虛點,那麼最後統計答案的時候需要特判。

#include #include #include #include #include using namespace std;

typedef unsigned long long ull;

typedef long long ll;

const int maxn=500010;

const ll mod=1000000007;

int n,rt,rt1,rt2,cnt;

int head[maxn],next[maxn<<1],to[maxn<<1],siz[maxn];

bool vis[maxn];

ull hs[maxn];

ll f[2][maxn],ine[maxn],jcc[maxn];

vectorch[maxn];

bool cmp(int a,int b)

while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();

return ret*f;

}void findr(int x,int fa)

void add(int a,int b)

void gethash(int x)

ll calc(ll a,ll b)

void dfs(int x) }}

int main()

else printf("%lld",(f[0][rt]+f[1][rt])%mod);

return 0;

}

BZOJ3162 獨釣寒江雪

bzoj 你要給乙個樹上的每個點黑白染色,要求白點不相鄰。求本質不同的染色方案數。兩種染色方案本質相同當且僅當對樹重新標號後對應節點的顏色相同。n le 5 times10 5 首先考慮沒有本質相同那個限制怎麼做。直接設 f 表示 i 點染成黑色 白色時子樹內的方案數。轉移很簡單 f prod j ...

BZOJ 3162 獨釣寒江雪

題意是求一棵無根樹本質不同獨立集的個數 那個所謂 極寒點 的選取就是獨立集。結構相同就是樹同構,完全相同就是樹的形態和獨立集都相同。我們先求出樹的重心,就可以轉化為有根樹同構問題。令 f u 1 為在 u 的子樹中,選取 u 的方案樹,f u 0 為在 u 的子樹中,不選取 u 的方案數。得到最基本...

BZOJ3162 獨釣寒江雪(樹雜湊,動態規劃)

bzoj 忽然翻到這道題目,突然發現就是前幾天一道考試題目。題解 樹雜湊,既然只考慮這一棵樹,那麼,如果兩個點為根是同構的,他們的重心相同,所以直接找出樹的重心,以重心為根進行轉移 提前預處理每一棵子樹的雜湊值,因為相同的子樹是同構的,所以轉移相當於是可重組合的計算。對於存在兩個重心的情況,分兩個重...