繁華模擬賽 Evensgn 剪樹枝

2022-03-27 10:56:07 字數 2738 閱讀 2191

繁華中學有一棵蘋果樹。蘋果樹有 n 個節點(也就是蘋果),n − 1 條邊(也就

是樹枝)。調皮的 evensgn 爬到蘋果樹上。他發現這棵蘋果樹上的蘋果有兩種:一

種是黑蘋果,一種是紅蘋果。evensgn 想要剪掉 k 條樹枝,將整棵樹分成 k + 1 個

部分。他想要保證每個部分裡面有且僅有乙個黑蘋果。請問他一共有多少種剪樹枝

的方案?

第一行乙個數字 n,表示蘋果樹的節點(蘋果)個數。

第二行一共 n − 1 個數字 p0, p1, p2, p3, ..., pn−2,pi 表示第 i + 1 個節點和 pi 節

點之間有一條邊。注意,點的編號是 0 到 n − 1。

第三行一共 n 個數字 x0, x1, x2, x3, ..., xn−1。如果 xi 是 1,表示 i 號節點是黑

蘋果;如果 xi 是 0,表示 i 號節點是紅蘋果。

輸出乙個數字,表示總方案數。答案對$10^+7$取模

100 1 2 1 4 4 4 0 8

0 0 0 1 0 1 1 0 0 1

27

考試就沒咋打這題,於是就騙了十分

正解:樹規

我們設$has[i]$表示節點$i$及其子樹帶乙個黑蘋果對父節點產生的方案數貢獻

$no[i]$表示節點$i$及其子樹不帶黑蘋果對父節點產生的方案數貢獻

我們從葉節點開始討論

當該葉子為紅蘋果時,顯然無法對父節點產生帶黑蘋果的方案數貢獻,而且它是葉子節點,所以可以對父節點產生$1$的不帶黑蘋果的方案數貢獻,故:

$$has[i]=1,no[i]=0$$

當該節點為黑蘋果時,顯然可以對父節點產生帶黑蘋果的方案數貢獻,而且它是葉子節點,所以可以對父節點產生$1$的帶乙個黑蘋果的方案數貢獻。我們再考慮,當我們砍斷它與父節點之間的邊時,它也可以對父節點產生$1$的不帶黑蘋果的方案數貢獻,故:

$$has[i]=1,no[i]=1$$

當該節點不為葉子節點時:

假如該節點為黑蘋果,那麼顯然,它的子樹無法對他產生帶乙個黑蘋果的方案數貢獻(我們先假設它的子樹可以,那麼,以該節點為根節點的子樹就一定有兩個或以上的黑蘋果,顯然是不合法的方案,故捨去)

所以,它的子樹對它只能產生不帶黑蘋果的方案數貢獻。

由乘法原理:

$$\prod^{}_no[j]$$

並且,由與黑蘋果葉子節點同樣的推理方式,我們可以得到:

$$no[i]=has[i]$$

原因仍然是砍斷它與父節點之間的邊所能造成的貢獻

假如該節點為紅蘋果,我們先考慮$has[i]$,因為它是乙個紅蘋果,所以它自己不能產生對父節點帶乙個黑蘋果的貢獻,所以,我們要對子樹的$has[j]$進行處理,我們考慮,當該節點的某一棵子樹產生了乙個黑蘋果的貢獻時,其它子樹就不能再貢獻黑蘋果了,所以,我們列舉每一棵子樹的$has$值,與其它子樹的$no$值相乘(同樣是乘法原理)(注意這裡,實際上有賭資料的成分,假如資料給個菊花樹,瞬間**,菊花樹:除了根節點,其他點深度均為1,即根節點為所有其他點的父節點的樹的簡稱,然而還是跑的賊快2333),再取和即為其值,即:

$$has[i]=\sum ^{}_(has[i]\times \prod^{}_no[k])$$

再考慮$no$值就很簡單了,首先,假如它的子樹都不產生黑蘋果貢獻,那麼它自然不可以對父節點產生貢獻,所以首先取個累乘,接著,假如它的子樹產生了黑蘋果貢獻,只要我們砍掉它與父節點之間的邊,它仍然可以產生該貢獻,所以:

$$no[i]=\prod^{}_no[j]+has[i]$$

**:

1 #include2 #include3 #include4

using

namespace

std;

5 inline int

read()

12const

int mod=1000000007;13

struct

edgea[200005

];16

int pre[100005

],tot;

17 inline void insert(int s,int

e)22 typedef long

long

l;23

int fa[100005

];24

intn;

25int w[100005

];26 l has[100005],no[100005

];27 inline void dfs(int

u)36}37

if(!flag)

43 has[u]=no[u]=1;44

return;45

}46if(w[u]==1)53

return;54

}55 has[u]=0;56

for(int i=pre[u];i!=-1;i=a[i].n)

67 has[u]=(has[u]+tmp)%mod;68}

69 no[u]=1;70

for(int i=pre[u];i!=-1;i=a[i].n)

76 no[u]=(no[u]+has[u])%mod;77}

78int

main()

86for(int i=0;i)

87 w[i]=read();

88 dfs(0

);89 printf("

%lld

",has[0

]);90 }

view code

Evensgn 剪樹枝 樹規

f x 0 表示與其父邊相連的連通塊內沒有黑蘋果的方案數,f x 1 則表示有黑蘋果,如果父邊被切斷,相當於沒有黑蘋果 初始化時,假設切掉父邊,f x 0 1,f x 1 0 遞迴回時轉移,每遞迴回乙個子樹,f x 1 f x 1 f v 0 f x 0 f v 1 f x 0 f x 0 f v ...

《省賽模擬賽補》

c題 比賽的時候已經想到了統計最底層的每個序列的出現次數,但是一開始想的是建圖之後dfs處理,但是發現很難處理出來。其實正確的思路是拓撲排序去處理次數。我們在最後建圖完成之後,倒著從n回去拓撲即可。但是這裡有個坑點,就是一開始統計入度可能是不正確的。例如 3 1 2 4 1 2 3是1,2的父節點,...

日常模擬賽

none 100 100 10 210 不太會做.好像.是個sb題.嗯.div3t1難度 include include define int long long define gc getchar define pc putchar inline int read void print int x...