小 Q 的棋盘
时间限制: 1 Sec 内存限制: 512 MB题目描述
小 Q 正在设计一种棋类游戏。
在小 Q 设计的游戏中,棋子可以放在棋盘上的格点中。某些格点之间有连线,棋子只
能在有连线的格点之间移动。整个棋盘上共有 V 个格点,编号为0,1,2 … , V − 1,它们是连通
的,也就是说棋子从任意格点出发,总能到达所有的格点。小 Q 在设计棋盘时,还保证棋
子从一个格点移动到另外任一格点的路径是唯一的。
小 Q 现在想知道,当棋子从格点 0 出发,移动 N 步最多能经过多少格点。格点可以重
复经过多次,但不重复计数。
输入
输入文件 chessboard.in。
第一行包含2个正整数V, N,其中 V 表示格点总数,N 表示移动步数。
接下来V − 1行,每行两个数ai, bi,表示编号为ai, bi的两个格点之间有连线。
输出
输出文件 chessboard.out。
输出一行一个整数,表示最多经过的格点数量。
样例输入
5 2
1 0
2 1
3 2
4 3
样例输出
3
提示
对于 100%的测试点,V, N ≤ 100, 0 ≤ ai, bi < V
来源
很显然,这是棵树。
我觉得这题可以水过去,看到题之后会有想到之前做过的铲雪车问题,
在树上有最长链是应该被重复走得最少的,然后其他的点如果想要走过去的话就应该要从最长链上的某一点走出去,然后再回到这一点
因为不会有环,所以链接非最长链上的点的边一定会被走两次(来一次去一次),
搜一下最长链,分类讨论
1,走不完最长链->步数
2,走完整棵树->V
3,(步数-最长链)/2+最长链
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int Max=105;
int N,V,Ans;
int cnt;
int d[Max];
int L[Max<<1],nxt[Max<<1],fir[Max<<1];
int max(int a,int b){return a<b?b:a;}
int min(int a,int b){return a<b?a:b;}
void add(int a,int b){L[++cnt]=b,nxt[cnt]=fir[a],fir[a]=cnt;}
void Dfs(int x,int fa){
Ans=max(Ans,d[x]);
for(int i=fir[x]; i; i=nxt[i])if(L[i]!=fa){
d[L[i]]=d[x]+1;
Dfs(L[i],x);
}
}
int main(){
scanf("%d%d",&V,&N);
int a,b;
for(int i=1; i<V; ++i){
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
}
d[0]=1;
Dfs(0,-1);
if(N+1<=Ans) printf("%d\n",N+1);
else {
Ans=Ans+((N-Ans+1)>>1);
printf("%d\n",min(Ans,V));
}
return 0;
}