题目:
题目意思:就是土拨鼠在起始点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;
}