测试地址:小Q的棋盘
做法:这一题是之前做的,现在整理一下放在这里。
这一题应该使用DFS来完成。
注意到一个显然的结论:最优解中一条边一定不会被走过两次以上,而且走过一次的边一定会连成一条链。那么我们应该找到一条尽量长的从点0出发的链,在这条链上走一次能走到一个新点,这一点用DFS就可以求出。如果还剩下步数,那么就在路径中间伸出的枝杈上走两次来得到一个新点(有去有回),直到没有新点或者剩余步数不足为止,可以证明按这个方法找到的方案一定是最优的。复杂度
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int v,n,first[110]={0},tot=0,ans,maxdep=0;
struct edge {int v,next;} e[210];
void insert(int a,int b)
{
e[++tot].v=b,e[tot].next=first[a],first[a]=tot;
}
void dfs(int v,int dep,int f)
{
maxdep=max(dep,maxdep);
for(int i=first[v];i;i=e[i].next)
if (e[i].v!=f) dfs(e[i].v,dep+1,v);
}
int main()
{
scanf("%d%d",&v,&n);
for(int i=1,a,b;i<v;i++)
{
scanf("%d%d",&a,&b);
insert(a,b),insert(b,a);
}
dfs(0,0,-1);
if (maxdep>n) printf("%d",n+1);
else printf("%d",min(maxdep+(n-maxdep)/2+1,v));
return 0;
}