• 洛谷 P2680 运输计划(NOIP2015提高组)(BZOJ4326)


    题目背景

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

    题目描述

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

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

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

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

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

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

    输入输出格式

    输入格式:

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

    接下来 (n-1) 行描述航道的建设情况,其中第 (i) 行包含三个整数 (a_i, b_i)​ 和 (t_i)​,表示第 (i) 条双向航道修建在 (a_i)​ 与 (b_i)​ 两个星球之间,任意飞船驶过它所花费的时间为 (t_i)​。数据保证 (1 leq a_i,b_i leq n)(0 leq t_i leq 1000)

    接下来 (m) 行描述运输计划的情况,其中第 (j) 行包含两个正整数 (u_j)​ 和 (v_j)​,表示第 (j) 个运输计划是从 (u_j)​ 号星球飞往 (v_j)​号星球。数据保证 (1 leq u_i,v_i leq n)

    输出格式:

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

    输入输出样例
    输入样例#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

    题解

    二分答案+树上差分

    显然,这个答案是具有单调性的,那么我们就可以二分答案

    考虑如何写check呢?

    设当前check(x)
    f[u] 表示 u到它父亲这条路径被超过长度x的线路经过次数

    首先我们记下长度超过x的线路数量为cnt,并把该路径经过的边 f 加1(树上差分)

    然后如果存在一条边经过次数等于cnt,且最长的线路长度减去它的长度小于等于x 就可以

    Code

    #include<bits/stdc++.h>
    #define LL long long
    #define RG register
    using namespace std;
    
    inline int gi() {
        int f = 1, s = 0;
        char c = getchar();
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        if (c == '-') f = -1, c = getchar();
        while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
        return f == 1 ? s : -s;
    }
    const int N = 300010;
    struct node {
    	int to, next, w;
    }g[N<<1];
    int last[N], gl;
    inline void add(int u, int v, int w) {
    	g[++gl] = (node) {v, last[u], w};
    	last[u] = gl;
    	return ;
    }
    struct zz {
    	int to, id;
    };
    vector<zz> q[N];
    int cx[N], cy[N], fa[N], lca[N];
    
    inline int find(int x) {
    	return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    bool vis[N];
    int ff[N], dep[N], fl[N], cnt;
    void tarjan(int u, int f) {
    	vis[u] = 1;
    	for (int i = last[u]; i; i = g[i].next) {
    		int v = g[i].to;
    		if (v == f) continue;
    		fl[v] = g[i].w;
    		dep[v] = dep[u]+g[i].w;
    		tarjan(v, u);		
    		fa[v] = u;
    	}
    	for (RG int i = 0; i < (int) q[u].size(); i++)
    		if (vis[q[u][i].to] && !lca[q[u][i].id])
    			lca[q[u][i].id] = find(q[u][i].to);
    	return ;
    }
    int MAX;
    void dfs(int u, int f) {
    	for (RG int i = last[u]; i; i = g[i].next) {
    		int v = g[i].to;
    		if (v == f) continue;
    		dfs(v, u);
    		ff[u] += ff[v];
    	}
    	if (cnt == ff[u] && fl[u] > MAX) MAX = fl[u];
    	return ;
    }
    int m;
    bool check(int x) {
    	cnt = 0;
    	int len = 0;
    	memset(ff, 0, sizeof(ff));
    	for (RG int i = 1; i <= m; i++)
    		if (dep[cx[i]]+dep[cy[i]]-dep[lca[i]]*2 > x) {
    			ff[cx[i]]++; ff[cy[i]]++; ff[lca[i]] -= 2;
    			cnt++;
    			len = max(dep[cx[i]]+dep[cy[i]]-dep[lca[i]]*2, len);
    		}
    	MAX = 0;
    	dfs(1, 0);
    	if (len - MAX <= x) return 1;
    	return 0;
    }
    
    int main() {
    	int n = gi(), js = 0; m = gi();
    	for (RG int i = 1; i < n; i++) {
    		int u = gi(), v = gi(), w = gi();
    		add(u, v, w); add(v, u, w);
    		js += w;
    	}
    	for (RG int i = 1; i <= n; i++) fa[i] = i;
    	for (RG int i = 1; i <= m; i++) {
    		cx[i] = gi(), cy[i] = gi();
    		q[cx[i]].push_back((zz){cy[i], i});
    		q[cy[i]].push_back((zz){cx[i], i});
    	}
    	tarjan(1, 0);
    	int l = 0, r = js, ans = js;
    	while (l <= r) {
    		int mid = (l + r) >> 1;
    		if (check(mid))
    			r = mid-1, ans = mid;
    		else l = mid+1;
    	}
    	printf("%d
    ", ans);
        return 0;
    }
    
    
    
  • 相关阅读:
    dubbo
    Executer invokeAll
    java并发编程实战 java并发编程的艺术 阅读随笔
    小程序如何获取指定类名高度
    一些好用的Swift三方框架
    微信小程序checkbox多选传多个参数的操作
    关于xcode出现An unknown error occurred. See the install log for more details安装失败解决办法
    iOS 针对于13.0和暗黑模式出现的适配问题
    iOS UITextField如何禁止输入表情及特殊字符
    判断iPhoneX适配问题
  • 原文地址:https://www.cnblogs.com/zzy2005/p/9872526.html
Copyright © 2020-2023  润新知