这道题真的做得头皮发麻
题解。。。lyd书上。。。
头皮发麻
。。。
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=600000+10; const int nil=0x3f3f3f3f; struct my{ int next; int w; int v; }; my bian[maxn*2]; queue<int>Q; int adj[maxn],fa,n,pre[maxn],d[maxn],p,path[maxn],top,sum1[maxn],sum2[maxn],q[maxn]; bool c[maxn]; void myinsert(int u,int v,int w){ bian[++fa].v=v; bian[fa].next=adj[u]; bian[fa].w=w; adj[u]=fa; } int bfs(int x){ while(!Q.empty()) Q.pop(); memset(d,0x3f,sizeof(d)); d[x]=0; pre[x]=0; Q.push(x); while(!Q.empty()){ int u=Q.front();Q.pop(); for (int i=adj[u];i;i=bian[i].next){ int v=bian[i].v; if(d[v]==nil){ d[v]=d[u]+bian[i].w; pre[v]=i; Q.push(v); } } } int p=1,y=1; for (;p<=n;p++) if(d[y]<d[p]) y=p; return y; } void dp1(int x,int f){ for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(c[v]&&v!=f){ sum1[v]=sum1[x]+bian[i].w; dp1(v,x); } } } void dp2(int x,int f){ for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(c[v]&&v!=f){ sum2[v]=sum2[x]+bian[i].w; dp2(v,x); } } } void get(){ p=bfs(1); p=bfs(p); } void lu(){ for (;pre[p];p=bian[pre[p]^1].v) {//可以记录路径,但是一直没搞懂是怎么回事,可能是我太弱吧,记住好了 // printf("%d %d ",bian[pre[p]].v,bian[pre[p]^1].v); if(!c[bian[pre[p]].v]) path[++top]=bian[pre[p]].v; if(!c[bian[pre[p]^1].v]) path[++top]=bian[pre[p]^1].v; c[bian[pre[p]].v]=true; c[bian[pre[p]^1].v]=true; } } void dfs(int x){ c[x]=1; for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(c[v]) continue; //printf("%d %d\n",x,v); dfs(v); d[x]=max(d[x],d[v]+bian[i].w); } } int main(){ //freopen("1999.in","r",stdin); // freopen("1999.out","w",stdout); fa=1; int u,v,w; int s; scanf("%d%d",&n,&s); for (int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&w); myinsert(u,v,w); myinsert(v,u,w); } get(); lu(); //for (int i=1;i<=top;i++) printf("%d ",path[i]); dp1(path[1],path[1]); dp2(path[top],path[top]); memset(d,0,sizeof(d)); for (int i=1;i<=top;i++) dfs(path[i]); int ans=nil; int pp=0; for (int i=1;i<=top;i++){ pp=max(pp,d[path[i]]); } int ppl=0; int i=1,j=1; for (;i<=top,j<=top;i++){ ppl=0; while(j<=top&&abs(sum1[path[j]]-sum1[path[i]])<=s) j++; ppl=max(ppl,pp); ppl=max(ppl,sum1[path[i]]); ppl=max(ppl,sum2[path[j]]); ans=min(ans,ppl); } printf("%d\n",ans); return 0; }
还是画图理解一下
设路径p为最长的不经直径路径,那么p必小于w(u,v),所以v之后路径都比p长
所以了嘛,答案要么就是p,要么就在直径上
对,没毛病
丝毫没毛病