#4700. Acc

題目描述

題解

今天明明沒什麼難題還打得這麼爛可見我太菜了

考慮一個被access過的樹,如果把一些沒有經歷過虛實邊轉化的虛邊刪去的話,那我們可以發現剩下的虛邊條數對應的就是這棵樹被access過的最小次數-1

於是可以考慮dp: fu,if_{u,i} 表示 uu 子樹內有i條經歷了虛實邊轉化的虛邊,考慮轉移的時候要注意 uu 這個點最多連結一個實兒子。特殊的,一棵樹是空的也要特殊處理。

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=10005,M=505,P=998244353;
int n,m,hd[N],sz[N],V[N<<1],nx[N<<1],t,f[N][M],s,g[N][M][2],G[M][2];
void add(int u,int v){
	nx[++t]=hd[u];V[hd[u]=t]=v;
}
void dfs(int u,int fr){
	sz[u]=g[u][0][0]=1;
	for (int v,i=hd[u];i;i=nx[i]){
		if ((v=V[i])==fr) continue;dfs(v,u);
		for (int j=0;j<sz[u] && j<m;j++)
			for (int k=0;k<sz[v] && k+j<m;k++){
				if (j+k+1<m)
					(G[j+k+1][0]+=1ll*g[u][j][0]*f[v][k]%P)%=P,
					(G[j+k+1][1]+=1ll*g[u][j][1]*f[v][k]%P)%=P;
				(G[j+k][1]+=1ll*g[u][j][0]*f[v][k]%P)%=P;
			}
		for (int j=0;j<m;j++)
			(G[j][0]+=g[u][j][0])%=P,
			(G[j][1]+=(g[u][j][0]+g[u][j][1])%P)%=P;
		for (int j=0;j<m;j++)
			g[u][j][0]=G[j][0],G[j][0]=0,
			g[u][j][1]=G[j][1],G[j][1]=0;
		sz[u]+=sz[v];
	}
	for (int j=0;j<m;j++)
		f[u][j]=(g[u][j][0]+g[u][j][1])%P;
	f[u][0]=(f[u][0]+P-1)%P;
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1,x,y;i<n;i++)
		scanf("%d%d",&x,&y),
		add(x,y),add(y,x);
	dfs(1,0);
	for (int i=0;i<m;i++)
		(s+=f[1][i])%=P;
	cout<<(s+1)%P<<endl;
	return 0;
}
發佈了161 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章