搜索题--------------2020暑假牛客多校第九场 K The Flee Plan of Groundhog

题目:

在这里插入图片描述
题目意思:就是土拨鼠在起始点1去往n号点找好朋友O玩,在出发t秒后,O的体温上升了,得病了,现在它要向土拨鼠靠近,但是土拨鼠有预知能力,知道O生病,他要远离O,避免得病,土拨鼠的速度是每秒1米,O的速度是2米每秒,问在最优的策略下,O要花多少时间才能追上土拨鼠。

思路:总体上就是用四次DFS来解答

  • 第一次DFS只要是记录从1号点到n号点的线路,找到t秒后土拨鼠到达的位置(如果土拨鼠提前到达,则直接输出0),这里因为是树,(n个点,n-1条边,这个条件可以得出),所以我们用DFS来求就可以,因为到达n点的路只有一条,所以就是最优的路;如果是图,那我们就要用迪杰斯特拉最短路算法来求。这里求的时候,我们fa[]数组记录路线,也就是哪个点是哪个点的父亲,其次就是剪枝,遍历过的点不再遍历
  • 第二次DFS,主要是从t秒后土拨鼠的位置开始,遍历当前点到每个点所用的时间
  • 第三次DFS,这个跟第二次的作用一样,求出O的点到每个点所用的时间
  • 第四次DFS,递归遍历每个点中的土拨鼠到达的时间和O到达的时间进行比较,只要是土拨鼠的时间大于O的时间,那么这个点就可以考虑,这里要注意一下叶节点的情况。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=1e5+100;
vector<int> vec[MAXN];//存边
int dep[MAXN],fa[MAXN],cs,blk[MAXN];
//blk Orange的时间 fa 父节点 dep 两个用处,见下面注释
int n,t,ans;
void dfs(int x,int depth,int fx)
{
    
    
	dep[x]=depth;
	for(int i=0;i<vec[x].size();i++){
    
    
		int s=vec[x][i];
		if(s==fx) continue;
		fa[s]=x;dfs(s,depth+1,x);
	}
}//预处理的dfs,先求出以1为根的向n的dep,然后方能求ts后现在的位置
//后面的用处是找土拨鼠的时间,存在dep里
void dfs1(int x,int depth,int fx)
{
    
    
	blk[x]=depth/2;
	for(int i=0;i<vec[x].size();i++){
    
    
		int s=vec[x][i];
		if(s==fx) continue;
		dfs1(s,depth+1,x);
	}
}//找Orange的时间,存在blk里
void getans(int x,int fx)
{
    
    
	bool fl=0;
	for(int i=0;i<vec[x].size();i++){
    
    
		int s=vec[x][i];			
		if(s==fx) continue;fl=1;
		if(dep[s]>=blk[s]){
    
    //不合法的点
			ans=max(blk[x],ans);
			continue;
		}
		getans(s,x);
	}
	if(!fl){
    
    
		ans=max(ans,blk[x]);
	}//叶节点
}//然后以当前位置为根,找到每条链能走的最远的地方
int main()
{
    
    
	int x,y;
	scanf("%d%d",&n,&t);
	for(int i=1;i<n;i++){
    
    
		scanf("%d%d",&x,&y);
		vec[x].push_back(y);
		vec[y].push_back(x);
	}
	dfs(1,0,-1);
	int gol=dep[n]-t,rt;//gol 走完ts后与n的距离 rt 根
	if(gol<=0){
    
    puts("0");return 0;}//如果ts后已经到了,那么Orange就直接抓住了土拨鼠
	for(int i=n,j=gol+1;j;i=fa[i],j--) rt=i;//找出t秒之后当前的位置,rt
	memset(dep,0,sizeof(dep));
	memset(blk,0,sizeof(blk));
	dfs(rt,0,-1);//得出土拨鼠的时间
	dfs1(n,1,-1);//得出Orange的时间
	ans=-1;getans(rt,-1);//得出答案
	printf("%d\n",ans);
}

# include <iostream>
# include <cmath>
using namespace std;
const int N = 1e5+100;
int nex[N],head[N],to[N],w[N],idx;
int tm_tuboshu[N],tm_o[N],fa[N];
int ans ;

void add(const int& a,const int& b){
    
    
	nex[++idx] = head[a];
	head[a] = idx;
	to[idx] = b;
}

void dfs(int x,int step,int fx){
    
    
	tm_tuboshu[x] = step;
	for(int i=head[x];i;i=nex[i]){
    
    
		int y = to[i];
		if(y==fx)  continue;
		fa[y] = x;
		dfs(y,step+1,x);
	}
}

void dfs_1(int x,int step,int fx){
    
    
	tm_o[x] = step/2;
	for(int i=head[x];i;i=nex[i]){
    
    
		int y = to[i];
		if(y==fx) continue;
		dfs(y,step+1,x);
	}
}

void dfs_2(int x,int fx){
    
    
	bool fl = 0;
	for(int i=head[i];i;i=nex[i]){
    
    
		int y = to[i];
		if(y==fx) continue;
		fl  = 1;
		if(tm_tuboshu[x]>=tm_o[x]){
    
    
			ans = max(ans,tm_o[x]);
			continue ;
		}
		dfs_2(y,x);
	}
	if(!fl)
		ans = max(ans,tm_o[x]);
}
int main(void)
{
    
    
	int n,t;
	cin>>n>>t;
	for(int i=1;i<n;++i){
    
    
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	
	dfs(1,0,-1);
	int st = tm_tuboshu[n] - t;
	if(st<0){
    
    
		cout<<"0"<<endl;
		return 0;
	}

	int bk ;
	for(int i=n,j=st;j;--j){
    
        //找到t秒后土拨鼠的位置
		i = fa[n];
		bk = i;
	}
  //  cout<<bk<<endl;

	for(int i=0;i<N;++i){
    
    
		tm_tuboshu[i]=0;
		tm_o[i] = 0;
	}

	dfs(bk,0,-1);    //第二次DFS
	dfs_1(n,1,-1);   //第三次DFS
	ans = -1;
	dfs_2(bk,-1);
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43743711/article/details/107923422