BZOJ3124 SDOI2013直径
本以为必有高论,结果是个思博题。随便找一条直径,最后答案肯定是这条直径上的连续一段,如果某分支长度等于直径上某端的长度这一端都要被剪掉。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,p[N],fa[N],son[N],t,cnt,root,x; ll deep[N],ans; struct data{int to,nxt,len; }edge[N<<1]; void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} void dfs(int k,int from) { for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=from) { deep[edge[i].to]=deep[k]+edge[i].len; fa[edge[i].to]=k; dfs(edge[i].to,k); } } ll findmax(int k) { ll mx=deep[k]; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) mx=max(mx,findmax(edge[i].to)); return mx; } void solve(int k) { ll mx=0; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) mx=max(mx,findmax(edge[i].to)); if ((deep[k]<<1)==mx&&mx) cnt=0; if (mx==ans) {cout<<cnt<<endl;exit(0);} if (son[k]) cnt++,solve(son[k]); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3124.in","r",stdin); freopen("bzoj3124.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<n;i++) { int x=read(),y=read(),z=read(); addedge(x,y,z),addedge(y,x,z); } deep[1]=0;dfs(1,1); root=1;for (int i=2;i<=n;i++) if (deep[i]>deep[root]) root=i; deep[root]=0;fa[root]=0;dfs(root,root); x=1;for (int i=2;i<=n;i++) if (deep[i]>deep[x]) x=i; ans=deep[x];cout<<ans<<endl; while (fa[x]) son[fa[x]]=x,x=fa[x]; solve(root); return 0; }