• noip2015运输计划


    有一棵带边权有根树,有m个运输计划,你可以把一条边变成0,所有计划一起开始

    求完成所有计划的最短时间

    sol:

    先二分,我们发现,用时mid以下的计划是没用的(要所有计划都完成)

    mid以上的计划,如果不相交,直接就是false

    如果相交,找到他们最大的一条交边,把那条边变成0,然后看最大计划 - 最大交边边权是否大于mid

    不大于mid就是true

    求交边可以用树上差分

    树上差分统计的时候可以用dfs序,可以...省栈空间

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 300010;
    int n,m;
    struct edg{int to,val;};
    vector<edg> G[maxn];
    int lg[maxn],fa[maxn],dep[maxn],delt[maxn],dis[maxn],bl[maxn],size[maxn];
    int ui[maxn],vi[maxn],dfn[maxn],DFN;
    int LCA[maxn],len[maxn];
    inline void dfs1(int x)
    {
        size[x] = 1;
        for(auto data : G[x])
        {
            int to = data.to,va = data.val;
            if(to == fa[x])continue;
            fa[to] = x;
            dep[to] = dep[x] + 1;dis[to] = dis[x] + va;
            dfs1(to);size[x] += size[to];
        }
    }
    inline void dfs2(int x,int col)
    {
        int k = 0;
        bl[x] = col;dfn[++DFN] = x;
        for(auto data : G[x])
        {
            int to = data.to,va = data.val;
            if(size[to] > size[k] && dep[to] > dep[x])k = to;
        }
        if(!k)return;
        dfs2(k,col);    
        for(auto data : G[x])
        {
            int to = data.to,va = data.val;
            if(to != k && dep[to] > dep[x])dfs2(to,to);
        }
    }
    inline int lca(int x,int y)
    {
        while(bl[x] != bl[y])
        {
            if(dep[bl[x]] < dep[bl[y]])swap(x,y);
            x = fa[bl[x]];
        }
        return dep[x] < dep[y] ? x : y;
    }
    inline int caldis(int x,int y){return dis[x] + dis[y] - 2 * dis[lca(x,y)];}
    int nowu[maxn],nowv[maxn];
    inline void getdelt(int x)
    {
        for(auto data : G[x])
        {
            int to = data.to;
            if(to == fa[x])continue;
            getdelt(to);delt[x] += delt[to];
        }
    }
    inline int chk(int x)
    {
        memset(delt,0,sizeof(delt));
        int curlen = 0,mx = 0,cnt = 0,maxw = 0;
        for(int i=1;i<=m;i++)
            if(caldis(ui[i],vi[i]) > x)
            {
                delt[ui[i]]++;
                delt[vi[i]]++;
                delt[lca(ui[i],vi[i])] -= 2;
                mx = max(mx,caldis(ui[i],vi[i]));
                cnt++;
            }
        for(int i=n;i>=2;i--)
        {
            delt[fa[dfn[i]]] += delt[dfn[i]];
            if(delt[dfn[i]] == cnt)maxw = max(maxw,dis[dfn[i]] - dis[fa[dfn[i]]]);
        }
    //    cout<<mx - maxw<<":"<<x<<endl;
        return mx - maxw <= x;
    }
    int main()
    {
        int mx = 0;
        n = read(),m = read();
        for(int i=2;i<=n;i++)
        {
            int u = read(),v = read(),w = read();
            //mx = max(mx,w);
            G[u].push_back((edg){v,w});G[v].push_back((edg){u,w});
        }dfs1(1);dfs2(1,1);
        //return 0;
        for(int i=1;i<=m;i++)
        {
            ui[i] = read(),vi[i] = read();
            LCA[i] = lca(ui[i],vi[i]);
            len[i] = dis[ui[i]] + dis[vi[i]] - 2 * dis[LCA[i]];
            mx = max(mx,len[i]);
        }
        //return 0;
        int l = 0,r = mx,ans;
        //cout<<l<<" "<<r<<endl;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            if(chk(mid))r = mid - 1,ans = mid;
            else l = mid + 1;
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    Python学习第75天(js历史和引入,模块复习)
    Python学习第74天(抽屉习题笔记)
    Python学习第73天(shelve模块、习题练习)
    Js查漏补缺02-各种数据类型
    Js查漏补缺01-js学习笔记
    开篇
    小小python欢乐多
    阅读笔记09 个人对于三年来软件工程的一点心得
    14周周博客
    软件杯第二阶段
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9754818.html
Copyright © 2020-2023  润新知