ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CQOI2017] 小Q的棋盘

2020-10-27 08:02:02  阅读:214  来源: 互联网

标签:走向 int max include 子树 CQOI2017 棋盘 出发


[CQOI2017] 小Q的棋盘

题目链接:洛谷P3698

题意简述

给定一棵树,点数为n,从根节点出发,每一步可以走向与当前点有直接边相连的点,问走m步最多能经过多少个点。边和点均可以重复经过,但不重复计数。

算法概述

\(f[p][j]\) 表示从 \(p\) 出发走向以 \(p\) 为根的子树,一共走 \(k\) 步并且最终回到 \(p\),最多能经过的点数。

\(g[p][j]\) 表示从 \(p\) 出发走向以 \(p\) 为根的子树,一共走 \(k\) 步并且最终不回到 \(p\),最多能经过的点数。

考虑 \(f[p][j]\) 的转移,走的情况应该是从 \(p\) 出发,走向某棵子树,再走回 \(p\),再走向某棵子树,再走回 \(p\),……,最后走回 \(p\)。

枚举 \(p\) 的所有子树,对于当前的子树 \(x\),考虑分配给其多少步 \(k\),由于还要走回 \(p\),故 \(k\) 的范围即是 \([0,j-2]\),状态转移方程即为:

\[f[p][j]=\mathop{max}_{2<=j<=m}\{f[p][j-k-2]+f[x][k]\} \]

边界:\(f[p][0]=1\)。

考虑 \(g[p][j]\) 的转移,对于当前的子树 \(x\),走的情况无非以下两种:

  • 从 \(p\) 出发走向其他子树最后回到 \(p\),再走向 \(x\) 的子树,最后不回来。
  • 从 \(p\) 出发走向 \(x\) 的子树最后回到 \(p\) ,再走向 \(p\) 的其他子树,最后不回来。

对于第一种情况:

\[g[p][j]=\mathop{max}_{1<=j<=m,0<=k<=j-1}\{f[p][j-k-1]+g[x][k]\} \]

对于第二种情况:

\[g[p][j]=\mathop{max}_{2<=j<=m,0<=k<=j-2}\{g[p][j-k-2]+f[x][k]\} \]

边界:\(g[p][0]=1\)。

最后的答案为 \(g[0][1 \ldots m]\) 中的最大值,因为如果不足 \(m\) 步就达到了最大值的话,剩下的步数可以随便走。

参考代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=110;
struct Edge{
	int to,nex;
}edge[N<<1];int idx;
int h[N];

void add_edge(int u,int v){edge[++idx]={v,h[u]};h[u]=idx;}

int f[N][N];
int g[N][N];
int n,m;

void dfs(int p,int fa)
{
	f[p][0]=g[p][0]=1;
	for(int i=h[p];~i;i=edge[i].nex)
	{
		int to=edge[i].to;
		if(to==fa)continue;
		dfs(to,p);
		for(int j=m;j>=1;j--)
			for(int k=j-1;k>=0;k--)
			{
				g[p][j]=max(g[p][j],f[p][j-k-1]+g[to][k]);
				if(j-k-2>=0)
					f[p][j]=max(f[p][j],f[p][j-k-2]+f[to][k]),
					g[p][j]=max(g[p][j],g[p][j-k-2]+f[to][k]);
			}
	}
}

int main()
{
	memset(h,-1,sizeof h);
	scanf("%d%d",&n,&m);
	for(int i=1,a,b;i<=n-1;i++)
	{
		scanf("%d%d",&a,&b);
		add_edge(a+1,b+1);
		add_edge(b+1,a+1);
	}
	dfs(1,0);
	int ans=0;
	for(int i=1;i<=m;i++)ans=max(ans,g[1][i]);
	printf("%d\n",ans);
	return 0;
}

标签:走向,int,max,include,子树,CQOI2017,棋盘,出发
来源: https://www.cnblogs.com/ninedream/p/13882427.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有