[Explanations] luoguP2680 transport plan

Quite hard a question, but pricey quality.
luoguP2680

See maximum minimum, the first thought is two points.
Each point may be pretreated to the root node distance dis array, and then find lca distance between two points of each path, i.e., dis [u] + dis [v ] -2 * dis [lca (u, v)]
I previously used a tree T cross LCA but a lot of points QAQ, would not have changed the multiplier.
(?) And then use a more basic algorithm - a tree difference, is used to determine whether mid feasible solution.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=300005;
int n,m,tot,mlen,num,tem,ans;
int head[N],ver[2*N],nxt[2*N],w[2*N];
int t[N],dis[N],f[N][27],a[N],dep[N];

struct path
{
    int u,v,len,lc;
} p[N];

inline int get()
{
    int res=0;char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9')
    {
        res=res*10+c-'0';
        c=getchar();
    }
    return res;
}

inline void add(int x,int y,int z)
{
    ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;w[tot]=z;
}

void dfs(int u,int fa)
{
    dep[u]=dep[fa]+1;
    for(int i=0;i<=24;i++)
        f[u][i+1]=f[f[u][i]][i];
    for(int e=head[u];e;e=nxt[e])
    {
        int v=ver[e];
        if(v==fa) continue;
        f[v][0]=u;
        a[v]=w[e];
        dis[v]=dis[u]+w[e];
        dfs(v,u);
    }
}

inline int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=24;i>=0;i--)
    {
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
        if(x==y) return x;
    }
    for(int i=24;i>=0;i--)
    {
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}

void dfs3(int u,int f)
{
    for (int e = head[u]; e ; e = nxt[e])
    {
        int v=ver[e];
        if(v==f) continue;
        dfs3(v,u);
        t[u]+=t[v];
    }
    if(t[u]==num&&a[u]>tem) tem=a[u];
}

inline bool check(int x)
{
    memset(t,0,sizeof(t));
    num=tem=0;
    for (int i = 1; i <= m; i++)
        if (p[i].len>x)
        {
            t[p[i].u]++;
            t[p[i].v]++;
            t[p[i].lc]-=2;
            num++;
        }
    dfs3(1,0);
    if(mlen-tem>x) return false;
    return true;
}

int main()
{
    int x,y,z;
    n=get(),m=get();
    for (int i = 1; i < n; i++)
    {
        x=get(),y=get(),z=get();
        add(x,y,z),add(y,x,z);
    }
    dfs(1,0);
    for (int i = 1; i <= m ; i++)
    {
        p[i].u=get(),p[i].v=get();
        p[i].lc=lca(p[i].u,p[i].v);
        p[i].len=dis[p[i].u]+dis[p[i].v]-2*dis[p[i].lc];
    }
    for (int i = 1; i <= m; i++)
        mlen=max(mlen,p[i].len);
    int l=0,r=mlen,mid;
    while (l<r)
    {
        mid=(l+r)>>1;
        if (check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
}

Guess you like

Origin www.cnblogs.com/zxj-hans/p/11266941.html