1. 程式人生 > >bzoj 4813: [Cqoi2017]小Q的棋盤

bzoj 4813: [Cqoi2017]小Q的棋盤

演算法:dfs(樹型DP)+貪心

難度:NOIP

題解:

先把圖中的最長鏈找到,然後分類討論:

  1. 步數使得它在鏈上跑
  2. 跑完了全圖
  3. 跑完了鏈,但是跑不完全圖

鏈上的點只經過一次,消耗1步;

其它的點經過後需要返回這條鏈上,消耗2步。

程式碼如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cmath>
#include <algorithm>
#define ll long long
#define N 105
using namespace std;
struct node
{
	int next;
	int to;
}edge[N<<1];
int head[N],dep[N];
int cnt=1;
void init()
{
	memset(head,-1,sizeof(head));
	cnt=1;
}
void add(int u,int v)
{
	edge[cnt].next=head[u];
	edge[cnt].to=v;
	head[u]=cnt++;
}
void dfs(int rt,int fa)
{
	for(int i = head[rt];i != -1;i=edge[i].next)
	{
		int to=edge[i].to;
		if(to==fa) continue;
		dep[to]=dep[rt]+1;
		dfs(to,rt);
	}
}
int main()
{
	int n,p;
	scanf("%d%d",&n,&p);
	init();
	for(int i = 1;i < n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b),add(b,a);
	}
	dfs(0,-1);
	int dpp=0;
	for(int i = 1;i < n;i++)
	{
		dpp=max(dpp,dep[i]);
	}
	if(p<=dpp) printf("%d\n",p+1);
	else if(p+dpp>=(2*(n-1))/*注意,一共n-1條邊*/) printf("%d\n",n/*注意,跑完全圖後就是n個點*/);
	else printf("%d\n",dpp+(p-dpp)/2+1);
	return 0 ;
}