日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2021牛客暑期多校训练营4 D-Rebuild Tree(prufer序列+树形dp)

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021牛客暑期多校训练营4 D-Rebuild Tree(prufer序列+树形dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

D-Rebuild Tree

Prufer 是這樣建立的:每次選擇一個編號最小的葉結點并刪掉它,然后在序列中記錄下它連接到的那個結點。重復n?2n-2n?2次后就只剩下兩個結點,算法結束。(為什么不是n?1n-1n?1次呢?因為第n?1n-1n?1次操作序列記錄下的節點一定是nnn

一個 nnn個點 mmm條邊的帶標號無向圖有 kkk個連通塊。我們希望添加k?1k-1k?1條邊使得整個圖連通。方案數為nk?2?∏i=1ksin^{k-2}·\prod_{i=1}^{k}s_ink?2?i=1k?si?
證明考慮組合意義,詳細見 OIWIKIPrufer 序列

  • 有了上面結論,刪kkk條邊之后形成k+1k+1k+1個連通塊,設每個連通塊的大小為sis_isi?
    ?則生成樹個數為nk?1?∏i=1k+1sin^{k-1}·\prod_{i=1}^{k+1}s_ink?1?i=1k+1?si?,該題就是求∑split(n,k)nk?1?∏i=1k+1si=nk?1?∑split(n,k)∏i=1k+1si\sum_{\text{split(n,k)}}n^{k-1}·\prod_{i=1}^{k+1}s_i=n^{k-1}·\sum_{\text{split(n,k)}}\prod_{i=1}^{k+1}s_isplit(n,k)?nk?1?i=1k+1?si?=nk?1?split(n,k)?i=1k+1?si?
  • ∑split(n,k)∏i=1k+1si\sum_{\text{split(n,k)}}\prod_{i=1}^{k+1}s_isplit(n,k)?i=1k+1?si?可以考慮將問題轉化為等價問題:刪掉kkk條邊且在每個聯通塊選一個點的方案數(由于每個連通塊有sis_isi?種選擇即得出∏i=1k+1si\prod_{i=1}^{k+1}s_ii=1k+1?si?)。

設計dp:
fu,j,0/1f_{u,j,0/1}fu,j,0/1?表示uuu子樹內,刪了jjj條邊,是否選擇點的方案數。

#include<bits/stdc++.h> using namespace std; using ll=long long; template <class T=int> T rd() {T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg; } const int N=50010,mod=998244353; int n,m; vector<int> e[N]; ll qmi(ll a,ll b) {ll v=1;while(b){if(b&1) v=v*a%mod;b>>=1;a=a*a%mod;}return v; } ll f[N][105][2]; ll g[105][2]; int sz[N]; void dfs(int u,int fa) {sz[u]=1;f[u][0][0]=f[u][0][1]=1;for(auto v:e[u]){if(v==fa) continue;dfs(v,u);memset(g,0,sizeof g);for(int i=0;i<=min(sz[u]-1,m);i++)for(int j=0;j<sz[v]&&i+j<=m;j++){g[i+j][0]=(g[i+j][0]+f[u][i][0]*f[v][j][0]%mod)%mod;g[i+j][1]=(g[i+j][1]+f[u][i][0]*f[v][j][1]%mod+f[u][i][1]*f[v][j][0]%mod)%mod;if(i+j==m) continue;g[i+j+1][0]=(g[i+j+1][0]+f[u][i][0]*f[v][j][1]%mod)%mod;g[i+j+1][1]=(g[i+j+1][1]+f[u][i][1]*f[v][j][1]%mod)%mod;}sz[u]+=sz[v];memcpy(f[u],g,sizeof g);} } int main() {n=rd(),m=rd();for(int i=1;i<n;i++){int u=rd(),v=rd();e[u].push_back(v);e[v].push_back(u);}dfs(1,0);printf("%lld\n",f[1][m][1]*qmi(n,m-1)%mod);}

總結

以上是生活随笔為你收集整理的2021牛客暑期多校训练营4 D-Rebuild Tree(prufer序列+树形dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。