#bzoj3362#小Q的棋盘(贪心)

15 篇文章 0 订阅

小 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;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值