您的位置:首页 > 其它

BZOJ 4813 [Cqoi2017]小Q的棋盘

2017-04-28 20:54 399 查看
树形DP

记f[i][j]表示在i的子树里走j步最多能走多少个点。实际上的决策一定是先进一个i的儿子节点的子树,然后出来,再进一个子树,再出来……最后进一颗子树,也许还会出来。枚举在外面走多少步,转移到最后进去的子树即可。

#include<cstdio>
#include<algorithm>
#define N 105
using namespace std;
namespace runzhe2000
{
int n, s, ecnt, f

, siz
, last
;
struct edge{int next, to;}e[N<<1];
void addedge(int a, int b)
{
e[++ecnt] = (edge){last[a], b};
last[a] = ecnt;
}
void dp(int x,int fa)
{
siz[x] = 1; f[x][0] = 1;
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to; if(y == fa) continue;
dp(y,x); siz[x] += siz[y];
}
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to; if(y == fa) continue;
for(int j = 0; j <= s; j++)
{
for(int k = 0, kk = min(j>>1,siz[x]-siz[y]-1); k <= kk; k++)
{
j-2*k-1 >= 0
? f[x][j] = max(f[x][j], k+1+f[y][j-2*k-1])
: f[x][j] = max(f[x][j], k+1);
}
}
}
}
void main()
{
scanf("%d%d",&n,&s);
for(int i = 1; i < n; i++){int x, y; scanf("%d%d",&x,&y);addedge(++x,++y);addedge(y,x);}
dp(1,0); int ans = 0;
for(int i = 0; i <= s; i++) ans = max(ans, f[1][i]);
printf("%d\n",ans);
}
}
int main()
{
runzhe2000::main();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: