CF1294F Three Paths on a Tree
阿新 • • 發佈:2020-12-04
CF1294F Three Paths on a Tree
題意翻譯
給定一棵含 n\ (3\leq n\leq2\cdot 10^5)n (3≤n≤2⋅105) 個結點的無權樹,試找出三個結點 uu、vv、ww,\operatorname{s.t.}s.t.
\operatorname{card}({u,v\text{ 間的路徑}}\cup{v,w\text{ 間的路徑}}\cup{w,u\text{ 間的路徑}})card({u,v 間的路徑}∪{v,w 間的路徑}∪{w,u 間的路徑})
最大。
你需要輸出兩行:
第一行為 \max\operatorname{card}({u,v\text{ 間的路徑}}\cup{v,w\text{ 間的路徑}}\cup{w,u\text{ 間的路徑}})maxcard({u
第二行三個整數,即 uu、vv、ww,如有多種答案,輸出一種即可。
題解:
貪心+樹。
首先簡單想一想能發現:答案應該是樹的直徑加上所有不在直徑上的節點中,距離直徑最長的距離。
那麼只需要模擬這個過程就可以:
先兩次DFS求出樹的直徑(記錄路徑長和兩個端點),然後把直徑上所有節點打上標記,然後列舉所有非直徑上的節點,更新最大距離,就可以過了。
複雜度是\(O(n)\)級別。
程式碼:
#include<cstdio> using namespace std; const int maxn=2e5+5; int n; int tot,head[maxn],nxt[maxn<<1],to[maxn<<1]; int maxx,pos[4],ans; int deep[maxn],fa[maxn]; bool v[maxn]; void add(int x,int y) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } void dfs(int x,int f,int p) { if(p==2) fa[x]=f; deep[x]=deep[f]+1; if(deep[x]>maxx) { maxx=deep[x]; pos[p]=x; } for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y==f) continue; dfs(y,x,p); } } int main() { scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } deep[0]=-1; dfs(1,0,1); maxx=0; dfs(pos[1],0,2); int x=pos[2]; while(x) { v[x]=1; x=fa[x]; } ans+=maxx; maxx=0; int tmp=0; for(int i=1;i<=n;i++) { if(v[i]) continue; else { x=i; tmp=0; while(!v[x]) { x=fa[x]; tmp++; } if(maxx<tmp) { maxx=tmp; pos[3]=i; } } } if(!maxx) for(int i=1;i<=n;i++) if(v[i]&&i!=pos[1]&&i!=pos[2]) { pos[3]=i; break; } ans+=maxx; printf("%d\n%d %d %d\n",ans,pos[1],pos[2],pos[3]); return 0; }