(抱歉又发帖子了)
如果把边的方向都视作从根节点往下,那么链大概有(↙↘ 或 ↓)两种形态。
维护出度入度,则:
不能有出度 ≥3 的点;
入度为 0 的点有且仅有一个(将其称作顶点)
出度为 0 的点的个数 = 顶点出度(一个黑点的情况特判一下)
(当然,肯定是没过去)
所以这些条件是否充要?
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read(){
int ret=0;
char c=getchar();
while(!('0'<=c&&c<='9')) c=getchar();
while('0'<=c&&c<='9') ret=(ret*10)+(c^48),c=getchar();
return ret;
}
int T,n,a,b;
const int N=2e5+10,M=4e5+10;
int to[M],nt[M],idx,h[N];
inline void add(int x,int y){
to[idx]=y;
nt[idx]=h[x];
h[x]=idx++;
}
int depth[N],dad[N];
int son[N];
bool v[N];
void dfs1(int u,int fa){
dad[u]=fa;
depth[u]=depth[fa]+1;
for(int i=h[u];i!=-1;i=nt[i]){
int j=to[i];
if(j==fa) continue;
dfs1(j,u);
}
}
int f[N],g[N];
void dfs(int u,int fa){
f[u]=g[u]=0;
int ma=0;
for(int i=h[u];i!=-1;i=nt[i]){
int j=to[i];
if(j==fa) continue;
dfs(j,u);
g[u]+=2+g[j];
ma=max(ma,g[j]-f[j]);
}
if(g[u]) f[u]=g[u]-1-ma;
}
inline void init(){
for(int i=0;i<=n;i++){
v[i]=false;
h[i]=-1;
}
idx=0;
}
int main(){
T=read();
while(T--){
n=read();
init();
a=read(),b=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
add(y,x);
}
dfs1(1,0);
int s=a,t=b,lca=0;
v[s]=v[t]=true;
if(s==t) lca=a;
while(true){
if(lca) break;
son[dad[s]]=s;
s=dad[s];
if(s&&v[s]){
lca=s;
break;
}
v[s]=true;
son[dad[t]]=t;
t=dad[t];
if(t&&v[t]){
lca=t;
break;
}
v[t]=true;
}
int ans=depth[a]+depth[b]-2*depth[lca];
int len=ans/2;
ans=len+(ans&1);
if(depth[a]-depth[lca]<=len){
len-=depth[a]-depth[lca];
while(len--) lca=son[lca];
}
else{
lca=a;
while(len--) lca=dad[lca];
}
dfs(lca,0);
printf("%d\n",ans+f[lca]);
}
return 0;
}