zoukankan      html  css  js  c++  java
  • noip2015 运输计划

    描述

    公元 2044 年,人类进入了宇宙纪元。L 国有 nn 个星球,还有 n1n−1 条双向航道,每条航道建立在两个星球之间,这 n1n−1 条 航道连通了 L 国的所有星球。

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

    为了鼓励科技创新,L 国国王同意小 PP 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

    在虫洞的建设完成前小 P 的物流公司就预接了 mm 个运输计划。在虫洞建设完成后, 这 mm 个运输计划会同时开始,所有飞船一起出发。当这 mm 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

    如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

    格式

    输入格式

    第一行包括两个正整数 nnmm,表示 L 国中星球的数量及小 P 公司预接的运输计划的 数量,星球从 11到 nn 编号。

    接下来 n1n−1 行描述航道的建设情况,其中第 ii 行包含三个整数 aiaibibi 和 titi,表示第 ii 条双向航道修建在 aiai 与 bibi 两个星球之间,任意飞船驶过它所花费的时间为 titi

    接下来 mm 行描述运输计划的情况,其中第 jj 行包含两个正整数 ujuj 和 vjvj,表示第 jj 个 运输计划是从ujuj 号星球飞往 vjvj 号星球。

    输出格式

    共 1 行,包含 1 个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

    我写了95分的二分,最后一个点莫名WA,可能是防AK的,不管了……

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn = 300105;
    struct edge{
        int v;
        int w;
        int id;
        int next;
    };
    struct QUERY{
        int lca;
        int dis;
        int s;
        int f;
    };
    long long n,m,flag,dep[maxn],dis_p[32][maxn],pa[32][maxn],vis[maxn],rec[maxn];
    int head[maxn],cnt;
    edge e[maxn];
    QUERY query[maxn];
    void ins(int u,int v,int w,int id){
        cnt++;
        e[cnt].v = v;
        e[cnt].w = w;
        e[cnt].id = id;
        e[cnt].next = head[u];
        head[u] = cnt; 
    }
    bool cmp(QUERY a,QUERY b){
        return a.dis < b.dis;
    }
    void input(){
        cin>>n>>m;
        edge tmp;
        int u,v,w;
        for(int i = 1;i <= n-1;i++){
            scanf("%d%d%d",&u,&v,&w);
            ins(u,v,w,i);
            ins(v,u,w,i);
        }
        for(int i = 1;i <= m;i++) scanf("%d%d",&query[i].s,&query[i].f);
    }
    void dfs(int x){
        int k = 0;
        while(pa[k][x] && pa[k][pa[k][x]]){
            pa[k+1][x] = pa[k][pa[k][x]];
            dis_p[k+1][x] = dis_p[k][x] + dis_p[k][pa[k][x]];
            k++;
        }
        for(int i = head[x];i;i = e[i].next){
            if(e[i].v != pa[0][x]){
                pa[0][e[i].v] = x;
                dep[e[i].v] = dep[x] + 1;
                dis_p[0][e[i].v] = e[i].w;
                rec[e[i].v] = e[i].id;
                dfs(e[i].v);
            }
        }
    }
    void get_dis(){
        int x,y,k,p,d;
        for(int i = 1;i <= m;i++){
            x = query[i].s;
            y = query[i].f;
            if(dep[x] > dep[y]) swap(x,y);
            p = dep[y] - dep[x];
            k = 0;
            d = 0;
            while(p){
                if(p&1){
                    d += dis_p[k][y];
                    y = pa[k][y];
                }
                p >>= 1;
                k++;
            }
            if(x == y){
                query[i].lca = x;
                query[i].dis = d;
                continue;
            }
            k = 0;
            while(k >= 0){
                if(pa[k][x] == pa[k][y]) k--;
                else{
                    d += dis_p[k][x] + dis_p[k][y];
                    x = pa[k][x];
                    y = pa[k][y];
                    k++;
                }
            }
            query[i].lca = pa[0][x];
            d += dis_p[0][x] + dis_p[0][y];
            query[i].dis = d;
        }
        sort(query+1,query+1+m,cmp);
    }
    bool check(int t){
        bool ok;
        int u,v;
        for(int i = m;i >= 1;i--){
            if(query[i].dis <= t) break;
            flag++;
            ok = false;
            u = query[i].s;
            while(u != query[i].lca){
                if(query[i].dis - dis_p[0][u] <= t && (i == m || vis[rec[u]] == flag-1)){
                    ok = true;
                    vis[rec[u]] = flag;
                }
                u = pa[0][u];
            }
            v = query[i].f;
            while(v != query[i].lca){
                if(query[i].dis - dis_p[0][v] <= t && (i == m || vis[rec[v]] == flag-1)){
                    ok = true;
                    vis[rec[v]] = flag;
                }
                v = pa[0][v];
            }
            if(!ok) return false;
        }
        return true;
    }
    void dvd(){
        int l = 0,r = query[m].dis,mid,ans;
        while(l <= r){
            mid = (l + r) >> 1;
            if(check(mid)){
                ans = mid;
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        cout<<ans;
    }
    int main(){
        input();
        dfs(1);
        get_dis();
        dvd();
        return 0;
    }
  • 相关阅读:
    HTML元素解释
    Java命名规范
    HDU 1058 Humble Numbers(DP,数)
    HDU 2845 Beans(DP,最大不连续和)
    HDU 2830 Matrix Swapping II (DP,最大全1矩阵)
    HDU 2870 Largest Submatrix(DP)
    HDU 1421 搬寝室(DP)
    HDU 2844 Coins (组合背包)
    HDU 2577 How to Type(模拟)
    HDU 2159 FATE(二维完全背包)
  • 原文地址:https://www.cnblogs.com/hyfer/p/5794028.html
Copyright © 2011-2022 走看看