洛谷P3884 二叉樹問題
阿新 • • 發佈:2018-12-20
題目描述
如下圖所示的一棵二叉樹的深度、寬度及結點間距離分別為:
深度:\(4\) 寬度:\(4\)(同一層最多結點個數)
結點間距離: \(⑧→⑥為8 (3×2+2=8)\)
\(⑥→⑦為3 (1×2+1=3)\)
注:結點間距離的定義:由結點向根方向(上行方向)時的邊數\(×2\),
與由根向葉結點方向(下行方向)時的邊數之和。
輸入輸出格式
輸入格式:
輸入檔案第一行為一個整數\(n(1≤n≤100)\),表示二叉樹結點個數。接下來的\(n-1\)行,表示從結點\(x\)到結點\(y\)(約定根結點為\(1\)),最後一行兩個整數\(u、v\),表示求從結點\(u\)到結點\(v\)
輸出格式:
三個數,每個數佔一行,依次表示給定二叉樹的深度、寬度及結點\(u\)到結點\(v\)間距離。
輸入輸出樣例
輸入樣例#1:
10
1 2
1 3
2 4
2 5
3 6
3 7
5 8
5 9
6 10
8 6
輸出樣例#1:
4
4
8
思路:對於第一個子問題,就是找樹上最深的點,一遍\(dfs\)即可實現,對於第二個子問題,就是看看相同深度的點數目的最大值是多少,對於對三個子問題,就是通過\(LCA\)
程式碼:
#include<cstdio> #include<algorithm> #define maxn 107 using namespace std; int f[maxn][7],n,x,y,js[maxn],maxx,head[maxn],num,d[maxn],zrj; struct node { int v,nxt; }e[maxn<<1]; inline void ct(int u, int v) { e[++num].v=v; e[num].nxt=head[u]; head[u]=num; } void dfs(int u, int fa) { for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v!=fa) { f[v][0]=u; d[v]=d[u]+1; maxx=max(maxx,d[v]); dfs(v,u); } } } inline int lca(int a, int b) { if(d[a]>d[b]) swap(a,b); for(int i=6;i>=0;--i) if(d[a]<=d[b]-(1<<i)) b=f[b][i]; if(a==b) return a; for(int i=6;i>=0;--i) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i]; return f[a][0]; } int main() { scanf("%d",&n); for(int i=1,u,v;i<n;++i) { scanf("%d%d",&u,&v); ct(u,v);ct(v,u); } dfs(1,0); for(int i=1;i<=n;++i) js[d[i]]++; for(int i=1;i<=maxx;++i) zrj=max(zrj,js[i]); for(int j=1;j<=6;++j) for(int i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1]; scanf("%d%d",&x,&y); printf("%d\n%d\n%d\n",maxx+1,zrj,(d[x]-d[lca(x,y)])*2-d[lca(x,y)]+d[y]); return 0; }