2019.03.08【JSOI2018】【洛谷P4516】【BZOJ5314】潜入行动(树形DP)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/88362720

洛谷传送门

BZOJ传送门


解析:

挺简单的一道树形DP,应该是出题人不想让输出0的拿太多分所以深度设置较小,其实应该先求一遍直径来判断是否有解再进行DP,懒得写了 ,这样才能保证复杂度。

f [ u ] [ i ] [ 0 / 1 ] [ 0 / 1 ] f[u][i][0/1][0/1] ,表示 u u 的子树中(包括 u u )放置了总共 i i 个监听器, u u 没放/放了,没被监听/被监听的方案数。

状态转移也非常好想,就在代码里面。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re char c;
		while(!isdigit(c=gc()));re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

cs int mod=1e9+7;
inline int add(cs int &a,cs int &b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,cs int &b){(a+=b)>=mod?a-=mod:0;}
inline int dec(cs int &a,cs int &b){return a<b?a-b+mod:a-b;}
inline int mul(cs int &a,cs int &b){return (ll)a*b%mod;}

cs int N=1e5+5,K=1e2+2;
vector<int> edge[N];
inline void addedge(int u,int v){
	edge[u].push_back(v);
	edge[v].push_back(u);
}

int n,k;
int f[N][K][2][2],g[K][2][2];
int siz[N];

inline void dfs(cs int &u,cs int &fa){
	f[u][0][0][0]=1;
	f[u][1][1][0]=1;
	siz[u]=1;
	for(int re e=edge[u].size()-1,v;~e;--e)
	if((v=edge[u][e])^fa){
		dfs(v,u);
		for(int re i=0,lim=min(siz[u],k);i<=lim;++i){
			g[i][0][0]=f[u][i][0][0];f[u][i][0][0]=0;
			g[i][0][1]=f[u][i][0][1];f[u][i][0][1]=0;
			g[i][1][0]=f[u][i][1][0];f[u][i][1][0]=0;
			g[i][1][1]=f[u][i][1][1];f[u][i][1][1]=0;
		}
		for(int re i=0,lim1=min(k,siz[u]);i<=lim1;++i)
		for(int re j=0,lim2=min(k-i,siz[v]);j<=lim2;++j){
			Add(f[u][i+j][0][0],mul(g[i][0][0],f[v][j][0][1]));
			
			Add(f[u][i+j][0][1],add(mul(g[i][0][0],f[v][j][1][1]),
									mul(g[i][0][1],add(f[v][j][0][1],f[v][j][1][1]))));
									
			Add(f[u][i+j][1][0],mul(g[i][1][0],add(f[v][j][0][1],f[v][j][0][0])));
			
			Add(f[u][i+j][1][1],add(mul(g[i][1][0],add(f[v][j][1][1],f[v][j][1][0])),
									mul(g[i][1][1],add(add(f[v][j][0][0],f[v][j][0][1]),
													add(f[v][j][1][0],f[v][j][1][1])))));
		}
		siz[u]+=siz[v];
	}
}

signed main(){
	n=getint();k=getint();
	for(int re i=1;i<n;++i)addedge(getint(),getint());
	dfs(1,0);
	cout<<add(f[1][k][1][1],f[1][k][0][1]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/88362720