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

 

posted @ 2018-10-08 15:47  探险家Mr.H  阅读(185)  评论(0编辑  收藏  举报