[题解]luogu_P4886_快递员(点分治
Posted superminivan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]luogu_P4886_快递员(点分治相关的知识,希望对你有一定的参考价值。
抄题解
#include<bits/stdc++.h> using namespace std; const int maxn=100009; int n,m; struct node{ int v,nxt,w; }e[maxn<<1]; int head[maxn],cnt; inline void add(int u,int v,int w){ e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt; } int siz[maxn],hev[maxn],rt,vis[maxn],sum,mx; void find(int x,int fa){ siz[x]=1;hev[x]=0; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v;if(y==fa||vis[y])continue; find(y,x); siz[x]+=siz[y]; hev[x]=max(hev[x],siz[y]); } hev[x]=max(hev[x],sum-siz[x]); if(hev[x]<mx)rt=x,mx=hev[x]; } int bel[maxn],dep[maxn];//属于哪个子树 void dfs(int x,int fa,int rr){ bel[x]=rr; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v;if(y==fa)continue; dep[y]=dep[x]+e[i].w; dfs(y,x,rr); } } int q[maxn],ans=1e9,X[maxn],Y[maxn]; void solve(int x){ if(vis[x]){ printf("%d ",ans); exit(0); } vis[x]=1; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v; dep[y]=e[i].w; dfs(y,x,y); } dep[x]=0; mx=0; q[0]=0; int last=0; for(int i=1;i<=m;i++) if(dep[X[i]]+dep[Y[i]]>mx)mx=dep[X[i]]+dep[Y[i]],q[q[0]=1]=i; else if(dep[X[i]]+dep[Y[i]]==mx)q[++q[0]]=i; ans=min(ans,mx); for(int i=1;i<=q[0];i++){ if(bel[X[q[i]]]!=bel[Y[q[i]]]){//有点对经过根不能更优 printf("%d ",ans);exit(0); } else if(!last)last=bel[X[q[i]]]; else if(last!=bel[X[q[i]]]){//两个点对不在同一子树,不能更优 printf("%d ",ans);exit(0); } } mx=1e9; sum=siz[last]; find(last,x); solve(rt); } int main(){ scanf("%d%d",&n,&m); for(int i=1,u,w,v;i<n;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w);add(v,u,w); } for(int i=1;i<=m;i++){ scanf("%d%d",&X[i],&Y[i]); } mx=1e9;sum=n;find(1,0); solve(rt); }
以上是关于[题解]luogu_P4886_快递员(点分治的主要内容,如果未能解决你的问题,请参考以下文章