[题解]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\n",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\n",ans);exit(0);
        }
        else if(!last)last=bel[X[q[i]]];
        else if(last!=bel[X[q[i]]]){//两个点对不在同一子树,不能更优 
            printf("%d\n",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);
}

 

posted @ 2019-10-28 20:05  羊肉汤泡煎饼  阅读(141)  评论(0编辑  收藏  举报