zoukankan      html  css  js  c++  java
  • [bzoj4326][NOIP2015]运输计划

    Description

    公元2044年,人类进入了宇宙纪元。

    L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球。

    P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从u_i号星球沿最快的宇航路径飞行到v_i号星球去。显然,飞船驶过一条航道是需要时间的,对于航道i,任意飞船驶过它所花费的时间为t_i,并且任意两艘飞船之间不会产生任何干扰。

    为了鼓励科技创新,L国国王同意小P的物流公司参与L国的航道建设,即允许小P把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小P的物流公司就预接了m个运输计划。在虫洞建设完成后,这m个运输计划会同时开始,所有飞船一起出发。当这m个运输计划都完成时,小P的物流公司的阶段性工作就完成了。如果小P可以自由选择将哪一条航道改造成虫洞,试求出小P的物流公司完成阶段性工作所需要的最短时间是多少?

    Input

    第一行包括两个正整数n,m,表示L国中星球的数量及小P公司预接的运输计划的数量,星球从1到n编号。接下来n-1行描述航道的建设情况,其中第i行包含三个整数 a_i,b_it_i,表示第i条双向航道修建在a_ib_i两个星球之间,任意飞船驶过它所花费的时间为t_i。数据保证 。接下来m行描述运输计划的情况,其中第i行包含两个正整数u_iv_i,表示第i个运输计划是从u_i号星球飞往v_i号星球。

    Output

    输出文件只包含一个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。

    Sample Input

    6 3
    1 2 3
    1 6 4
    3 1 7
    4 3 6
    3 5 5
    3 6
    2 5
    4 5

    Sample Output

    11

    HINT

    1$leq$n,m$leq$300000,1$leq$a_i,b_i$leq$n,0$leq$t_i$leq$1000,1$leq$u_i,v_i$leq$n

    Solution

    这道题就是求在一条边的时间不算的情况下,求u_iv_i的最大值的最小值.

    显然二分答案ans,然后判断对于所有花费时间>ans(u_i,v_i)的交是否为空.

    如果不为空,若

    max{(u_i,v_i)}-max{e[i].w|i属于所有花费时间>ans(u_i,v_i)的交}$leq$ans,则合法.

    求路径交是否为空=求是否存在一条边所有路径都经过.

    w[i]表示i连向它父亲的那条边有多少条路径经过,

    每次w[u_i]+1,w[v_i]+1,w[lca(u_i,v_i)]-2,向上传递即可.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define K 20
    #define N 300005
    #define M 600005
    #define INF 300000000
    using namespace std;
    typedef long long ll;
    struct graph{
        int nxt,to,w;
    }e[M];
    struct line{
        int l,r,f,w;
    }a[N];
    int f[N][K],g[N],t[N],w[N],ef[N],dep[N],n,m,mk,sum,cnt;
    bool v[N],flag;
    stack<int> s;
    inline int read(){
        int ret=0;char c=getchar();
        while(!isdigit(c))
            c=getchar();
        while(isdigit(c)){
            ret=(ret<<1)+(ret<<3)+c-'0';
            c=getchar();
        }
        return ret;
    }
    inline void addedge(int x,int y,int w){
        e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].w=w;
    }
    inline void dfs(int u){
        dep[u]=1;s.push(u);
        while(!s.empty()){
            u=s.top();s.pop();
            if(u==1) for(int i=0;i<K;++i)
                f[u][i]=1;
            else for(int i=1;i<K;++i)
                f[u][i]=f[f[u][i-1]][i-1];
            for(int i=g[u];i;i=e[i].nxt)
                if(!dep[e[i].to]){
                    s.push(e[i].to);
                    f[e[i].to][0]=u;
                    ef[e[i].to]=e[i].w; 
                    dep[e[i].to]=dep[u]+1;
                    t[e[i].to]=t[u]+e[i].w;
                }
        }
    }
    inline int swim(int x,int h){
        for(int i=0;h;++i,h>>=1)
            if(h&1) x=f[x][i];
        return x;
    }
    inline int lca(int x,int y){
        int i,t;
        if(dep[x]<dep[y]){
            t=x;x=y;y=t;
        }
        x=swim(x,dep[x]-dep[y]);
        if(x==y) return x;
        while(true){
            for(i=0;f[x][i]!=f[y][i];++i);
            if(!i) return f[x][0];
            x=f[x][i-1];y=f[y][i-1];
        }
    }
    inline void total(int u){
        s.push(u);
        memset(v,0,sizeof(v));
        while(!s.empty()){
            u=s.top();
            if(!v[u]){
                v[u]=true;
                for(int i=g[u];i;i=e[i].nxt)
                    if(dep[e[i].to]>dep[u])
                        s.push(e[i].to);
            }
            else{
                s.pop();
                for(int i=g[u];i;i=e[i].nxt)
                    if(dep[e[i].to]>dep[u])
                        w[u]+=w[e[i].to];
                if(w[u]==sum){
                    flag=true;
                    mk=max(mk,ef[u]);
                }
            }
        }
    }
    inline bool chk(int k){
        int ma=0;mk=sum=0;
        memset(w,0,sizeof(w));
        for(int i=1;i<=m;++i){
            if(a[i].w>k){
                ++sum;ma=max(ma,a[i].w);
                ++w[a[i].l];++w[a[i].r];w[a[i].f]-=2;
            }
        }
        flag=false;total(1);
        return flag&&ma-mk<=k;
    }
    inline void init(){
        n=read();m=read();
        for(int i=1,j,k,l;i<n;++i){
            j=read();k=read();l=read();
            addedge(j,k,l);addedge(k,j,l);
        }
        dfs(1);
        for(int i=1,j,k,l;i<=m;++i){
            a[i].l=read();a[i].r=read();
            a[i].f=lca(a[i].l,a[i].r);
            a[i].w=t[a[i].l]+t[a[i].r]-(t[a[i].f]<<1);
        }
        int l=0,r=INF,mid;
        while(l<r){
            mid=(l+r)>>1;
            if(chk(mid)) r=mid;
            else l=mid+1;
        }
        
        printf("%d
    ",l);
    }
    int main(){
        freopen("transport.in","r",stdin);
        freopen("transport.out","w",stdout);
        init();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    JavaScript实现类的private、protected、public、static以及继承
    OSS网页上传和断点续传(STSToken篇)
    OSS网页上传和断点续传(OSS配置篇)
    Linq sum()时遇到NULL
    SQLSERVER事务日志已满 the transaction log for database 'xx' is full
    笔记本高分辨软件兼容问题,字体太小或模糊
    H5上传图片之canvas
    An error occurred while updating the entries. See the inner exception for details.
    无限级结构SQL查询所有的下级和所有的上级
    SQLserver 进程被死锁问题解决
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6022261.html
Copyright © 2011-2022 走看看