码迷,mamicode.com
首页 > 其他好文 > 详细

CF1499F Diameter Cuts 树形dp

时间:2021-06-02 13:53:47      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:lan   +=   tin   状态   两种   操作   简单   i++   sig   

思考到树形dp,寻找某个子树上的根节点和他的儿子节点的关系。假设一个在节点u的子树上的答案ans,也就是节点u的子树里中的点构成的树,删掉的一些边后,构成的最长不超过k的链的构造方法数目。那么通过dp,u的解可以从遍历u的子节点v来推得。
在u吸收子节点们(v们)时,有两种可能,要么就是连一条边,要么就不连这条边。如果连接这条边的话。那么最长的链应该就是从u节点+1(这是(u,v)的长度)加子节点能够到的最深的距离。因为要加直径,所以还要加目前根节点到目前最深的节点的距离。
如果不连这条边,那么最长的链就是u节点已有的最长的链或者是v节点已有的最长的链。

可见在dp中为了维护答案还要再加一层“节点u为起点的最长的简单路径”dp[u][j]
每次u找一个新儿子dp的时候,dp[u][i]就是节点u为起点的最长为i的简单路径,dp[v][j]同理
for (v in son[u])
for i=[0,maxdep[i]-dep[i]] 就是u已有的状态的最深深度
for j=[0,maxdep[j]-dep[i]] 同理
不连这条边: tmpdp[u][i]=dp[u][i]dp[v][j] //其实可以保证j>k时dp[v][j]==0 因为所有的连边操作都被跳过了
连这条边:先判断能不能连:if (i+j+1<k) tmpdp[u][i]+=dp[u][i]
dp[v][j]

最后更新一下dp状态就可以了。

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
const int N = 5e3+10;
struct Edge{
    int u,v,next;
}e[N*2];
const int mod = 998244353;
int head[N],tot;
void add(int u,int v){
    e[++tot]={u,v,head[u]}; head[u]=tot;
}
int n,k;
int dep[N],maxdep[N];
int dp[N][N];
int tmp[N];
int siz[N];
void dfs(int u,int fa){
    siz[u]=1;maxdep[u]=dep[u];
	dp[u][0]=1;
	for (int ii=head[u];ii;ii=e[ii].next)
	{
        int v=e[ii].v;
		if(v==fa)continue;
		dep[v]=dep[u]+1;
		dfs(v,u);
		int kk=maxdep[u]-dep[u];
		FOR(i,0,max(maxdep[u],maxdep[v])-dep[u])tmp[i]=0;
		FOR(i,0,kk)
		{
			FOR(j,0,maxdep[v]-dep[u])
			{
				tmp[i]=(tmp[i]+1ll*dp[u][i]*dp[v][j]%mod)%mod;
				if(i+j+1>k)continue;
				tmp[max(i,j+1)]=(tmp[max(i,j+1)]+1ll*dp[u][i]*dp[v][j]%mod)%mod;
			}
		}
		maxdep[u]=max(maxdep[u],maxdep[v]);
		FOR(i,0,maxdep[u]-dep[u])dp[u][i]=tmp[i];
		siz[u]+=siz[v];
	}
}
int ans=0;
void solve(){
    dfs(1,0);
    for (int i=0;i<=k;i++) ans=(ans+dp[1][i])%mod;
    cout<<ans;
}
signed main(){
	
	cin>>n>>k;
    for (int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    solve();
}

CF1499F Diameter Cuts 树形dp

标签:lan   +=   tin   状态   两种   操作   简单   i++   sig   

原文地址:https://www.cnblogs.com/asanagiyantia/p/14820693.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!