题解 CF2207D Boxed Like a Fish
题解 CF2207D Boxed Like a Fish
其他题(几天后完工)
自评:下位蓝\~中位蓝。
题意
给定一棵
数据范围:多测,
做法
观察最后两组样例,发现它们之间仅
由于有 CD,所以最好的选择是干脆不预判,等对面差一格到叶子了再跳上去,这样尽可能让对面多跑。样例中当
也就是换句话说,C 从一个距离叶子为
进一步地,这样的两个叶子路径上的所有点全部都是危险的,因为 C 一旦跳上去就立刻符合上一句话的条件从而跑掉。为了方便我们取起点为根(特判起点就是叶子的情况)这样所有的叶子都是在子树内的,直接拿深度减一减就能判断当前点是否是危险的。然后必然能跑到危险的点上的点也全都是危险的,即最终危险的点的定义为:一个点
这显然是个递归的过程,维护每个点子树内最浅的危险的点即可。单组时间复杂度
//Please ignore those headfiles.I write them just because
//DEV-C++ won't support completion if i use <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<unordered_map>
#include<set>
#include<queue>
#define ll long long
#define ull unsigned long long
#define lf double
#define ld long double
#define LL __int128
#define ui unsigned int
using namespace std;
ll T,n,m,s,u,v,low[500010],dep[500010];
vector<ll> a[500010];
void dfs(ll now,ll lst){
dep[now]=dep[lst]+1;
ll mn=999999,sec=999999;
for(int i=0;i<a[now].size();i++){
if(a[now][i]!=lst){
dfs(a[now][i],now);
if(low[a[now][i]]<mn){
sec=mn;
mn=low[a[now][i]];
}
else if(low[a[now][i]]<sec){
sec=low[a[now][i]];
}
}
}
if(a[now].size()<=1||sec!=999999&&mn-dep[now]+sec-dep[now]<m+2){
low[now]=dep[now];
}
else{
low[now]=mn;
}
}
int main(){
ios::sync_with_stdio(0);
cin>>T;
while(T--){
cin>>n>>m>>s;
for(int i=1;i<n;i++){
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
if(a[s].size()>1){
dfs(s,0);
}
if(a[s].size()<=1||low[s]==1){
cout<<"YES\n";
}
else{
cout<<"NO\n";
}
for(int i=1;i<=n;i++){
a[i].clear();
}
}
return 0;
}