[CF735E]Ostap and Tree

Ostap and Tree

题解

看到这道题,是很容易想到树形dp的。

dp_{i,j}为在节点i的子树中,节点j是最近的黑点,且距离超过j的点都被满足的方案数。

对于在加入每一个u的子节点v可以发现,若i+j\leq 2k,则i\leq k\vee j<k,故而在连接两黑点的长度为i+j+1的路径上一定存在一点使得两点都可以满足条件,故f_{u,min(i,j+1)}+= f_{u,i}f_{v,j}

而当i+j>2k时,则有i> k\vee j\geq k,肯定存在一些点不满足条件,故f_{u,max(i,j)}+=f_{x,i}f_{y,j}

再令f_{u,k+1}为子树内只有自身不满足条件的情况,方便转移。

于是,答案就为\sum_{i=0}^{k}f_{1,i}O\left(nk^2 \right )的时间复杂度,不会超时。

源码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
using namespace std;
#define MAXN 105
typedef long long LL;
const LL mo=1e9+7;
typedef pair<LL,LL> pii;
#define gc() getchar()
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
}
int n,k,head[MAXN],tot;
LL dp[MAXN][MAXN],tmp[MAXN],ans;
struct edge{int v,nxt;}e[MAXN<<1];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
void dfs(int x,int fa){
	dp[x][0]=dp[x][k+1]=1;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].v;if(v==fa)continue;dfs(v,x);
		for(int j=0;j<=2*k;j++)tmp[j]=0;
		for(int j1=0;j1<=2*k;j1++)
			for(int j2=0;j2<=2*k;j2++)
				if(j1+j2<=2*k)(tmp[min(j1,j2+1)]+=dp[x][j1]*dp[v][j2]%mo)%=mo;
				else (tmp[max(j1,j2+1)]+=dp[x][j1]*dp[v][j2]%mo)%=mo;
		for(int j=0;j<=2*k;j++)dp[x][j]=tmp[j];
	}
}
signed main(){
	read(n);read(k);
	for(int i=1;i<n;i++){
		int u,v;read(u);read(v);
		addEdge(u,v);addEdge(v,u);
	}
	dfs(1,0);
	for(int i=0;i<=k;i++)(ans+=dp[1][i])%=mo;
	printf("%lld\n",ans);
	return 0;
}

谢谢!!!

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页