【CQOI2017】【BZOJ4813】小Q的棋盘 DFS

题目描述

  有一棵树,你要从\(0\)号点开始走,你可以走\(m\)步,问你最多能经过多少个不同的点。

  \(n\leq 100\)

题解

  出题人的做法是DP(一个简单的树形DP),但是可以直接通过一次DFS做出来。

  先DFS整棵树,设\(d\)为所有点深度的最大值。

  若\(m<d\),那么显然走这条最长的链是最优的,答案为\(m+1\)

  否则我们可以先沿着这条链走到底,在这个过程中可以往其他的子树走,每花两步可以走到一个新的点,答案为\(\min(n,d+\lfloor\frac{m-d+1}{2}\rfloor)\)

  时间复杂度:\(O(n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
	if(a>b)
		swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
	char str[100];
	sprintf(str,"%s.in",s);
	freopen(str,"r",stdin);
	sprintf(str,"%s.out",s);
	freopen(str,"w",stdout);
#endif
}
int rd()
{
	int s=0,c;
	while((c=getchar())<'0'||c>'9');
	do
	{
		s=s*10+c-'0';
	}
	while((c=getchar())>='0'&&c<='9');
	return s;
}
void put(int x)
{
	if(!x)
	{
		putchar('0');
		return;
	}
	static int c[20];
	int t=0;
	while(x)
	{
		c[++t]=x%10;
		x/=10;
	}
	while(t)
		putchar(c[t--]+'0');
}
int upmin(int &a,int b)
{
	if(b<a)
	{
		a=b;
		return 1;
	}
	return 0;
}
int upmax(int &a,int b)
{
	if(b>a)
	{
		a=b;
		return 1;
	}
	return 0;
}
int maxd;
vector<int> g[110];
void dfs(int x,int fa,int dep)
{
	maxd=max(maxd,dep);
	for(auto v:g[x])
		if(v!=fa)
			dfs(v,x,dep+1);
}
int main()
{
	open("chessbord");
	int n,m;
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		x++;
		y++;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0,1);
	int ans;
	if(m<maxd)
		ans=m+1;
	else
		ans=min(n,maxd+(m-maxd+1)/2);
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-04-22 21:14  ywwyww  阅读(174)  评论(0编辑  收藏  举报