[队内测试Day10.22T4][洛谷P2680]运输计划

来源:互联网 发布:制作照片合成软件 编辑:程序博客网 时间:2024/05/17 04:33

题目←

吐槽下考场上的魔改题面……
看出来是运输计划后,记得以前听说过是二分,于是开始摸鱼……
不会树链剖分,考场上卡掉一个点
尽管实现步骤很麻烦,但思路清晰的话,具体打起来还是比较容易的一道题
能摸出来大概是人品比较好……

#include<iostream>#include<cstdio>#include<algorithm>#define LL long longusing namespace std;const LL MAXN = 300000 + 50;struct edge{    LL f,t,v;}l[MAXN << 1];struct zt{    LL f,t;    LL v;    LL lca;}e[MAXN];LL head[MAXN],next[MAXN << 1],tot;void init(LL n){    for(LL i = 1;i <= n;i ++){        head[i] = -1;    }}void build(LL f,LL t,LL v){    l[++ tot] = (edge){f,t,v};    next[tot] = head[f];    head[f] = tot;}LL n,m,a,b,c;LL deep[MAXN],fa[MAXN][26];LL ru[MAXN];LL rank[MAXN];void dfs(LL p,LL f){    for(LL i = 1;i <= 25;i ++){        fa[f][i] = fa[fa[f][i - 1]][i - 1];    }    for(LL i = head[f];i != -1;i = next[i]){        LL t = l[i].t;        if(t == p)continue;        ru[t] ++;        deep[t] = deep[f] + 1;        fa[t][0] = f;        rank[t] = rank[f] + l[i].v;        dfs(f,t);    }}LL LCA(LL a,LL b){    if(deep[a] < deep[b])swap(a,b);    LL t = deep[a] - deep[b];    for(LL i = 0;i <= 25;i ++){        if(t & (1 << i)){            a = fa[a][i];        }    }    if(a == b)return a;    for(LL i = 25;i >= 0;i --){        if(fa[a][i] != fa[b][i]){            a = fa[a][i];            b = fa[b][i];        }    }    return fa[a][0];}LL topo[MAXN];LL L = 1,R = 1;void toposort(){    topo[R ++] = 1;    while(L != R){        LL u = topo[L];        for(LL i = head[u];i != -1;i = next[i]){            LL t = l[i].t;            ru[t] --;            if(!ru[t])topo[R ++] = t;        }        L ++;    }}LL mid;LL cf[MAXN];bool check(LL x){    LL cnt = 0;    LL maxx = 0;    for(LL i = 0;i <= n;i ++){        cf[i] = 0;    }    for(LL i = 1;i <= m;i ++){        if(e[i].v > x){            cf[e[i].f] ++;            cf[e[i].t] ++;            cf[e[i].lca] --;            cf[fa[e[i].lca][0]] --;            cnt ++;            maxx = max(maxx,e[i].v);        }    }    for(LL j = n;j >= 1;j --){        LL u = topo[j];        for(LL i = head[u];i != -1;i = next[i]){            LL t = l[i].t;            if(deep[t] < deep[u])continue;            cf[u] += cf[t];        }    }    for(LL u = 1;u <= n;u ++){        if(cf[u] < cnt)continue;        for(LL i = head[u];i != -1;i = next[i]){            if(deep[l[i].t] < deep[u])continue;            if(cf[l[i].t] >= cnt){                if(maxx - l[i].v <= x)return true;            }        }    }    return false;}void solve(){    R ++;    L --;    while(R - L > 1){        mid = L + R >> 1;        if(check(mid))R = mid;        else L = mid;    }}int main(){    freopen("Random.in","r",stdin);    freopen("Random.out","w",stdout);    scanf("%lld%lld",&n,&m);    init(n);    for(LL i = 1;i <= n - 1;i ++){        scanf("%lld%lld%lld",&a,&b,&c);        build(a,b,c);        build(b,a,c);    }    dfs(1,1);    toposort();    L = R = 0;    for(LL i = 1;i <= m;i ++){        scanf("%lld%lld",&e[i].f,&e[i].t);        LL lca = LCA(e[i].f,e[i].t);        e[i].v = rank[e[i].f] + rank[e[i].t] - 2*rank[lca];        e[i].lca = lca;        R = max(R,e[i].v);    }    solve();    printf("%lld",R);    fclose(stdin);    fclose(stdout);    return 0;}