• luogu P2680 运输计划 (二分答案+树上差分)


    题目背景

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

    题目描述

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

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

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

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

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

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

    输入输出格式

    输入格式:

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

    接下来 n-1n1 行描述航道的建设情况,其中第 ii 行包含三个整数 a_i, b_iai,bi 和 t_iti,表示第 ii 条双向航道修建在 a_iai 与 b_ibi两个星球之间,任意飞船驶过它所花费的时间为 t_iti。数据保证 1 leq a_i,b_i leq n1ai,bin 且 0 leq t_i leq 10000ti1000。

    接下来 mm 行描述运输计划的情况,其中第 jj 行包含两个正整数 u_juj 和 v_jvj,表示第 jj 个运输计划是从 u_juj 号星球飞往 v_jvj号星球。数据保证 1 leq u_i,v_i leq n1ui,vin

    输出格式:

    一个整数,表示小 PP 的物流公司完成阶段性工作所需要的最短时间。

    输入输出样例

    输入样例#1: 复制
    6 3 
    1 2 3 
    1 6 4 
    3 1 7 
    4 3 6 
    3 5 5 
    3 6 
    2 5 
    4 5
    输出样例#1: 复制
    11

    说明

    所有测试数据的范围和特点如下表所示

    请注意常数因子带来的程序效率上的影响。

    思路:

    很明显答案是递增的,我们可以直接二分答案,设最短时间为t,那么航线时间大于t的我们就把他放到差分数组里,然后在差分数组里找到所有链公有的权值最大的边权,看减去这条边后所有航线是否都小于等于之前假设的最短时间t,.

    这道题注意要用读入挂,要不一直TLE第13个样例。。。。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 3e5 + 10;
    int p[M][22],w[M],dep[M],cnt,head[M],n,ans,dist[M],num,mx,m,sum[M];
    int len[M],u[M],v[M],lc[M],r,l;
    struct node{
        int to,next,w;
    }e[M<<1];
    
    void Add(int u,int v,int w){
        e[++cnt].to = v;e[cnt].next = head[u];e[cnt].w = w,head[u] = cnt;
    }
    
    void dfs(int u,int fa,int deep){
        dep[u] = deep;
        p[u][0] = fa;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v == fa) continue;
            dist[v] = dist[u] + e[i].w;
            w[v] = e[i].w;
            dfs(v,u,deep+1);
        }
    }
    
    
    void get_fa(){
        for(int j = 1;(1<<j)<=n;j++)
            for(int i = 1;i <= n;i ++)
                p[i][j] = p[p[i][j-1]][j-1];
    }
    
    int lca(int a,int b){
        if(dep[a] > dep[b]) swap(a,b);
        int h = dep[b] - dep[a];
        for(int i = 0;(1<<i)<=h;i++){
            if((1<<i)&h) b = p[b][i];
        }
        if(a != b){
            for(int i = 20;i >= 0;i --){
                if(p[a][i] != p[b][i]){
                    a = p[a][i]; b = p[b][i];
                }
            }
            a = p[a][0];
        }
        return a;
    }
    
    void dfs1(int u,int fa){
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v == fa) continue;
            dfs1(v,u);
            sum[u] += sum[v];
        }
        if(sum[u] == num) mx = max(mx,w[u]);
    }
    
    bool check(int x){
        int k = 0;
        num = 0; mx = 0;
        memset(sum,0,sizeof(sum));
        for(int i = 1;i <= m;i ++){
            if(len[i] > x){
                sum[u[i]]++; sum[v[i]]++;
                sum[lc[i]] -= 2;
                num++;
                k = max(k,len[i]);
            }
        }
        dfs1(1,0);
        if(k - x <= mx) return 1;
        else return 0;
    }
    
    int read(){
        char c;int num,f=1;
        while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
        while(c=getchar(), isdigit(c))num=num*10+c-'0';
        return f*num;
    }
    
    inline bool read(int &num)
    {
            char in;bool IsN=false;
            in=getchar();
            if(in==EOF) return false;
            while(in!='-'&&(in<'0'||in>'9')) in=getchar();
            if(in=='-'){ IsN=true;num=0;}
            else num=in-'0';
            while(in=getchar(),in>='0'&&in<='9'){
                    num*=10,num+=in-'0';
            }
            if(IsN) num=-num;
            return true;
    }
    
    int main()
    {
        int a,b,c;
        read(n); read(m);
        for(int i = 1;i < n;i ++){
            read(a);read(b);read(c);
            Add(a,b,c); Add(b,a,c);
        }
        dfs(1,0,1); get_fa();
        for(int i = 1;i <= m;i ++){
            read(u[i]); read(v[i]);
            lc[i] = lca(u[i],v[i]);
            len[i] = dist[u[i]] + dist[v[i]] - 2*dist[lc[i]];
            r = max(r,len[i]);
        }
        int k = 0;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(check(mid)){
                k = mid;
                r = mid-1;
            }
            else l = mid+1;
        }
        printf("%d
    ",k);
    }
  • 相关阅读:
    zabbix(三)网页操作
    zabbix(二)安装客户端
    zabbix(一)安装服务端
    python操作git
    elasticsearch之match
    elasticsearch之查询的两种方式
    Git 命令集合啦
    Django contenttype 组件
    Django 中 related_name/related_query_name 的区别
    Django中的CharField 和 FileField 主要讲FileField
  • 原文地址:https://www.cnblogs.com/kls123/p/9992216.html
Copyright © 2020-2023  润新知