洛谷 P3698 [CQOI2017]小Q的棋盘 解题报告
P3698 [CQOI2017]小Q的棋盘
题目描述
小 Q 正在设计一种棋类游戏。
在小 Q 设计的游戏中,棋子可以放在棋盘上的格点中。某些格点之间有连线,棋子只能在有连线的格点之间移动。整个棋盘上共有 V 个格点,编号为0,1,2 … , V− 1,它们是连通的,也就是说棋子从任意格点出发,总能到达所有的格点。小 Q 在设计棋盘时,还保证棋子从一个格点移动到另外任一格点的路径是唯一的。
小 Q 现在想知道,当棋子从格点 0 出发,移动 N 步最多能经过多少格点。格点可以重复经过多次,但不重复计数。
输入输出格式
输入格式:
第一行包含2个正整数\(V\), \(N\),其中\(V\)表示格点总数,\(N\)表示移动步数。
接下来\(V−1\)行,每行两个数\(a_i,b_i\),表示编号为\(a_i,b_i\)的两个格点之间有连线。
输出格式:
输出一行一个整数,表示最多经过的格点数量。
说明:
对于 100%的测试点,\(N,V ≤ 100, 0 ≤a_i,b_i< V\)
我贪心算是废了
这个题真的不难想orz...
首先读题,这是一颗树。
然后发现最后一次走可以不回去,最后一次肯定走最长的链
然后其他的点多一次返回的开销
Code:
#include <cstdio>
const int N=102;
int min(int x,int y){return x<y?x:y;}
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
int mx=0,used[N],n,m;
void dfs(int now,int dep)
{
used[now]=1;
mx=mx>dep?mx:dep;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(!used[v])
dfs(v,dep+1);
}
}
int main()
{
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs(0,1);
if(m<mx-1)
printf("%d\n",m+1);
else
printf("%d\n",min(n,mx+(m-mx+1)/2));
return 0;
}
2018.7.11