樹網的核
阿新 • • 發佈:2020-07-25
樹網的核
根據直徑的性質,我們對任意直徑計算是等同的,故只要求出一條直徑就行了
然後我們將直徑上的點標記,為\(u_1,u_2,...,u_t\)
設\(d(u_x)\)為直徑上一點\(u_x\)不通過直徑上的邊能到達的最遠距離
我們列舉在直徑上距離不超過s的區間\((u_i,u_j)\),考慮\(ans=max(max_{i \leq k \leq j}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t))\)
又根據直徑的最長性,等價於\(ans=max(max_{1 \leq k \leq t}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t))\)
\(maxd=max_{1 \leq k \leq t}{d(u_k)}\)是定值,用two-pointer列舉i,j,\(O(N)\)解決
#include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define mp make_pair #define SZ(x) ((int)x.size()) #define ALL(x) x.begin(),x.end() #define U(i,u) for(register int i=head[u];i;i=nxt[i]) #define rep(i,a,b) for(register int i=(a);i<=(b);++i) #define per(i,a,b) for(register int i=(a);i>=(b);--i) using namespace std; typedef long double ld; typedef long long ll; typedef unsigned int ui; typedef pair<int,int> PII; typedef vector<int> VI; template<class T> inline void read(T &x){ x=0;char c=getchar();int f=1; while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f; } template<class T> inline void cmin(T &x, T y){x=x<y?x:y;} template<class T> inline void cmax(T &x, T y){x=x>y?x:y;} const int N=501; int n,s,g[N][N],head[N],nxt[N<<1],v[N<<1],w[N<<1],cnt,mx,p,q,vis[N],d[N]; int ss[N],tt[N],maxd; void add(int x,int y,int z){nxt[++cnt]=head[x];head[x]=cnt;v[cnt]=y;w[cnt]=z;} void dfs1(int now,int fa,int di){ if(di>mx)mx=di,p=now; U(i,now){ if(v[i]==fa)continue; dfs1(v[i],now,di+w[i]); } } int stak[N],sp; void dfs2(int now,int fa){ if(now==q){ stak[++sp]=now; return; }U(i,now){ if(v[i]==fa)continue; dfs2(v[i],now); if(vis[v[i]]){vis[now]=1;stak[++sp]=now;return;} } } void dfs3(int now,int fa,int di){ cmax(mx,di);U(i,now){ if(v[i]==fa)continue; if(vis[v[i]])continue; dfs3(v[i],now,di+w[i]); } } int main(){ read(n);read(s);rep(i,1,n-1){int x,y,z;read(x);read(y);read(z);add(x,y,z);add(y,x,z);g[x][y]=g[y][x]=z;} mx=0;dfs1(1,0,0);mx=0;q=p;dfs1(p,0,0); vis[p]=vis[q]=1;dfs2(p,0); rep(i,1,sp){mx=0;dfs3(stak[i],0,0);d[stak[i]]=mx;cmax(maxd,d[stak[i]]);} rep(i,2,sp)ss[i]=ss[i-1]+g[stak[i-1]][stak[i]];per(i,sp-1,1)tt[i]=tt[i+1]+g[stak[i+1]][stak[i]]; int ans=0x3f3f3f3f; rep(i,1,sp){ int j=i; while(ss[j]-ss[i]<=s&&j<=sp){ int tmp=max(maxd,max(ss[i],tt[j])); cmin(ans,tmp); ++j; } } printf("%d\n",ans); return 0; } /* 5 2 1 2 5 2 3 2 2 4 4 2 5 3 ans=5; */