树形dp求树上最长距离,然后单调队列维护。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn=5e4+9; vector < pair<int,int> > e[maxn]; int n,m; int dist[maxn][2]; void dfs(int t,int from) { for(vector < pair<int,int> >::iterator k=e[t].begin();k!=e[t].end();k++) { int u=k->first,w=k->second; if(u==from) continue; dfs(u,t); if(dist[u][0]+w>dist[t][0]) { dist[t][1]=dist[t][0]; dist[t][0]=dist[u][0]+w; } else if(dist[u][0]+w>dist[t][1]) { dist[t][1]=dist[u][0]+w; } } } void dfs2(int t,int from) { for(vector < pair<int,int> >::iterator k=e[t].begin();k!=e[t].end();k++) { int u=k->first,w=k->second,sum; if(u==from) continue; if(dist[t][0]!=w+dist[u][0]) sum=dist[t][0]+w; else sum=dist[t][1]+w; if(sum>dist[u][0]) { dist[u][1]=dist[u][0]; dist[u][0]=sum; } else if(sum>dist[u][1]) { dist[u][1]=sum; } dfs2(u,t); } } struct { int que[maxn],id[maxn]; int st,ed; }mmax,mmin; void getans(int tmp) { int ans=0; mmax.st=mmin.st=1; mmax.ed=mmin.ed=0; int id=0; for(int i=1;i<=n;i++) { while(mmax.ed>=mmax.st&&mmax.que[mmax.ed]<dist[i][0]) mmax.ed--; mmax.que[++mmax.ed]=dist[i][0]; mmax.id[mmax.ed]=i; while(mmin.ed>=mmin.st&&mmin.que[mmin.ed]>dist[i][0]) mmin.ed--; mmin.que[++mmin.ed]=dist[i][0]; mmin.id[mmin.ed]=i; while(mmax.que[mmax.st]-mmin.que[mmin.st]>tmp) { if(mmin.st==mmin.ed) { id=max(id,mmax.id[mmax.st]); mmax.st++; } else if(mmax.st==mmax.ed) { id=max(id,mmin.id[mmin.st]); mmin.st++; } else if(mmax.id[mmax.st]<mmin.id[mmin.st]) { id=max(id,mmax.id[mmax.st]); mmax.st++; } else { id=max(id,mmin.id[mmin.st]); mmin.st++; } } ans=max(ans,i-id); } cout<<ans<<endl; } int main() { // freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m),n||m) { for(int i=1;i<=n;i++) e[i].clear(); for(int i=1,from,to,w;i<n;i++) { scanf("%d%d%d",&from,&to,&w); e[from].push_back(make_pair(to,w)); e[to].push_back(make_pair(from,w)); } memset(dist,0,sizeof(dist)); dfs(1,-1); dfs2(1,-1); for(int i=1,tmp;i<=m;i++) { scanf("%d",&tmp); getans(tmp); } } return 0; }