影片連結:
P3304 [SDOI2013] 直徑 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)
// 兩次 DFS O(n) #include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=200005; struct edge{ int to,w,ne; }e[N<<1]; int head[N],idx; void add(int x,int y,int w){ e[++idx]={y,w,head[x]}; head[x]=idx; } int n,p,l,r,pre[N],col[N]; ll d[N],mxd; void dfs(int x,int fa){ pre[x]=fa; for(int i=head[x];i;i=e[i].ne){ int y=e[i].to,w=e[i].w; if(y==fa) continue; d[y]=d[x]+w; if(d[y]>mxd) mxd=d[y],p=y; dfs(y,x); } } void dfs2(int x,int fa){ for(int i=head[x];i;i=e[i].ne){ int y=e[i].to,w=e[i].w; if(col[y]||y==fa) continue; d[y]=d[x]+w; if(d[y]>mxd) mxd=d[y]; dfs2(y,x); } } int main(){ scanf("%d",&n); for(int i=1,x,y,z;i<n;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,0); d[p]=mxd=0; l=p; //記錄直徑左端點 dfs(p,0); r=p; //記錄直徑右端點 printf("%lld\n",mxd); for(int i=r;i;i=pre[i])col[i]=1; //標記直徑 int ll=l,rr=r; for(int i=pre[rr];i!=ll;i=pre[i]){ int ld=d[i],rd=d[rr]-d[i]; d[i]=mxd=0; dfs2(i,0); if(mxd==rd) r=i; if(mxd==ld){l=i;break;} } //區間[l,r]為公共路徑 if(l==r) puts("0"); else{ int cnt=1; for(int i=pre[r];i!=l;i=pre[i]) cnt++; printf("%d\n",cnt); } }