P3884 二叉树问题 题解
update 2024.9.27 修复挂掉的图
P3884 二叉树问题
传送门
本蒟蒻第一篇题解,前面的大佬都是 lca+dfs 或者 Floyd 做的,我不会lca,只能自己想了一个较为精巧的思路,不喜勿喷。
思路
我们可以将每两个点之间的边建为双向的,以一为根节点,则就有向上(蓝色)和向下(红色)两种边。
显然,从根节点遍历时所经过的都是红色边,蓝色边如何处理无关痛痒。先由
代码(附上关键注释)
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[110],idx;
int st[110];
int h[110],ne[220],e[220];
int size[110];
int x,y;
//建边
void add(int a,int b){
ne[idx]=h[a],e[idx]=b,h[a]=idx++;
}
//搜索深度和宽度
int dfs(int u,int deep,int fa){
size[deep]++;//深度为deep的宽度
int d=deep;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==fa)continue;
d=max(d,dfs(j,deep+1,u));//取最深的深度
}
return d;
}
//累加标记的边
int dfss(int u,int fa){
int ans=0;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==fa)continue;//保证不向上
ans+=st[i];
ans+=dfss(j,u);
}
return ans;
}
//搜索u->v或者v->u
bool query(int u,int en,int last,int flag){
if(u==en){
return true;//搜到目标点
}
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(j==last)continue;
if(query(j,en,u,flag)){//搜到了才能标记
st[i]=flag;//标记不同类型的边
return true;
}
}
return false;
}
signed main(){
int n;
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<n;i++){
int l,r;
cin>>l>>r;
add(l,r),add(r,l);//建双向边
}
int deep=dfs(1,1,0);//搜深度和宽度
int res=0;
for(int i=1;i<=deep;i++){
res=max(res,size[i]);
}
cin>>x>>y;
cout<<deep<<endl<<res<<endl;
query(y,x,0,2);//u到v
query(x,y,0,1);//v到u
cout<<dfss(1,0);
return 0;
}
完美收官~