• [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划


    [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划

    试题描述

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

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

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

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

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

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

    输入

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

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

    接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1≤ui,vi≤n

    输出

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

    输入示例

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

    输出示例

    11

    数据规模及约定

    测试点编号 n= m= 约定
    1 100 1  
    2 100 100 第i条航道连接i号星球与i+1号星球
    3 100 100  
    4 2000 1
    5 1000 1000 第i条航道连接i号星球与i+1号星球
    6 2000 2000 第i条航道连接i号星球与i+1号星球
    7 3000 3000 第i条航道连接i号星球与i+1号星球
    8 1000 1000  
    9 2000 2000
    10 3000 3000
    11 80000 1
    12 100000 1
    13 70000 70000

    第i条航道连接i号星球与i+1号星球

    14 80000 80000 第i条航道连接i号星球与i+1号星球
    15 90000 90000 第i条航道连接i号星球与i+1号星球
    16 100000 100000 第i条航道连接i号星球与i+1号星球
    17 80000 80000  
    18 90000 90000
    19 100000 100000
    20 300000 300000

    所有数据

        1<=ai,bi,uj,vj<=n,0<=ti<=1000

    题解

    留了好久的坑终于填上了。我们首先把每条链(即每个运输计划)的长度预处理出来,然后按照长度从大到小排序。

    因为我们发现如果想使答案减小,一定要让最长的链变短。我们需要将所有链长相同的链进行合并(即求交,不难发现多条链只要有交集,那么交集就是一条链),然后重复一下过程:

    1.) 对当前链找到它的边长最大值 mx,用 max{ 下一链长, 当前链长 - mx } 更新答案 ans;

    2.) 把下一条链与当前链合并(求交),作为下一轮的当前链;

    3.) 若这不是最后一条链,回到 1.)。

    4.) 最后答案就是 ans。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
     
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    
    #define maxn 300010
    #define maxm 600010
    #define maxlog 20
    #define oo 2147483647
    int n, m, q, head[maxn], next[maxm], to[maxm], dist[maxm];
    struct Que {
    	int a, b, d;
    	Que() {}
    	Que(int _1, int _2, int _3): a(_1), b(_2), d(_3) {}
    	bool operator < (const Que& t) const { return d > t.d; }
    } qs[maxn];
    
    void AddEdge(int a, int b, int c) {
    	to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
    	swap(a, b);
    	to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
    	return ;
    }
    
    int dep[maxn], Dep[maxn], fa[maxlog][maxn], mx[maxlog][maxn], L[maxn], R[maxn], clo, list[maxm], cl, pos[maxn];
    void build(int u) {
    	L[u] = ++clo; list[++cl] = u; pos[u] = cl;
    	for(int i = 1; i < maxlog; i++) {
    		int v = fa[i-1][u];
    		fa[i][u] = fa[i-1][v];
    		mx[i][u] = max(mx[i-1][u], mx[i-1][v]);
    	}
    	for(int e = head[u]; e; e = next[e]) if(to[e] != fa[0][u]) {
    		fa[0][to[e]] = u;
    		mx[0][to[e]] = dist[e];
    		dep[to[e]] = dep[u] + 1;
    		Dep[to[e]] = Dep[u] + dist[e];
    		build(to[e]);
    		list[++cl] = u;
    	}
    	R[u] = clo;
    	return ;
    }
    int Log[maxm], Lca[maxlog][maxm];
    void rmq_init() {
    	Log[1] = 0;
    	for(int i = 2; i <= cl; i++) Log[i] = Log[i>>1] + 1;
    	for(int i = 1; i <= cl; i++) Lca[0][i] = list[i];
    	for(int j = 1; (1 << j) <= cl; j++)
    		for(int i = 1; i + (1 << j) - 1 <= cl; i++) {
    			int a = Lca[j-1][i], b = Lca[j-1][i+(1<<j-1)];
    			Lca[j][i] = dep[a] < dep[b] ? a : b;
    		}
    	return ;
    }
    int lca(int a, int b) {
    	int l = min(pos[a], pos[b]), r = max(pos[a], pos[b]), t = Log[r-l+1];
    	a = Lca[t][l]; b = Lca[t][r-(1<<t)+1];
    	return dep[a] < dep[b] ? a : b;
    }
    int calc(int a, int b) {
    	return Dep[a] + Dep[b] - (Dep[lca(a,b)] << 1);
    }
    int calcmx(int a, int b) {
    	if(dep[a] < dep[b]) swap(a, b);
    	int Mx = 0;
    	for(int i = maxlog-1; i >= 0; i--) if(dep[a] - (1 << i) >= dep[b])
    		Mx = max(Mx, mx[i][a]), a = fa[i][a];
    	for(int i = maxlog-1; i >= 0; i--) if(fa[i][a] != fa[i][b])
    		Mx = max(Mx, max(mx[i][a], mx[i][b])),
    		a = fa[i][a], b = fa[i][b];
    	return a == b ? Mx : max(Mx, max(mx[0][a], mx[0][b]));
    }
    
    bool cmp(int a, int b) { return dep[a] > dep[b]; }
    bool isson(int pa, int son) { return L[pa] <= L[son] && L[son] <= R[pa]; }
    
    int main() {
    	n = read(); q = read();
    	for(int i = 1; i < n; i++) {
    		int a = read(), b = read(), c = read();
    		AddEdge(a, b, c);
    	}
    	build(1); rmq_init();
    	for(int i = 1; i <= q; i++) {
    		int u = read(), v = read();
    		qs[i] = Que(u, v, calc(u, v));
    	}
    	sort(qs + 1, qs + q + 1);
    //	for(int i = 1; i <= q; i++) printf("%d %d %d %d
    ", qs[i].a, qs[i].b, qs[i].d, lca(qs[i].a, qs[i].b));
    	int A = qs[1].a, B = qs[1].b, ans = oo;
    //	printf("%d %d(%d %d)
    ", qs[2].d, calcmx(A, B), A, B);
    	if(qs[1].d != qs[2].d || q == 1)
    		ans = min(ans, max(qs[2].d, qs[1].d - calcmx(A, B)));
    	for(int i = 2; i <= q; i++) {
    		int a = qs[i].a, b = qs[i].b, C = lca(A, B);
    		int ps[10];
    		ps[1] = lca(a, A); ps[2] = lca(a, B); ps[3] = lca(a, b);
    		ps[4] = lca(b, A); ps[5] = lca(b, B); ps[6] = lca(A, B);
    		sort(ps + 1, ps + 7, cmp);
    		int cp = unique(ps + 1, ps + 7) - ps;
    		A = ps[1]; B = ps[2];
    		bool ok = 1;
    		for(int j = 3; j <= cp; j++)
    			if(!isson(ps[j], A) || !isson(ps[j], B)) {
    				ok = 0; break;
    			}
    		if(!ok) break;
    		if(qs[i].d != qs[i+1].d || i == q)
    			ans = min(ans, max(qs[i+1].d, qs[1].d - calcmx(A, B)));
    //		printf("[%d %d]
    ", A, B);
    	}
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    

    2016-10-29 uoj 上自己 hack 自己成功,下面是 AC 代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
      
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
     
    #define maxn 300010
    #define maxm 600010
    #define maxlog 20
    #define oo 2147483647
    int n, m, q, head[maxn], next[maxm], to[maxm], dist[maxm];
    struct Que {
        int a, b, d;
        Que() {}
        Que(int _1, int _2, int _3): a(_1), b(_2), d(_3) {}
        bool operator < (const Que& t) const { return d > t.d; }
    } qs[maxn];
     
    void AddEdge(int a, int b, int c) {
        to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
        swap(a, b);
        to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;
        return ;
    }
     
    int dep[maxn], Dep[maxn], fa[maxlog][maxn], mx[maxlog][maxn], L[maxn], R[maxn], clo, list[maxm], cl, pos[maxn];
    void build(int u) {
        L[u] = ++clo; list[++cl] = u; pos[u] = cl;
        for(int i = 1; i < maxlog; i++) {
            int v = fa[i-1][u];
            fa[i][u] = fa[i-1][v];
            mx[i][u] = max(mx[i-1][u], mx[i-1][v]);
        }
        for(int e = head[u]; e; e = next[e]) if(to[e] != fa[0][u]) {
            fa[0][to[e]] = u;
            mx[0][to[e]] = dist[e];
            dep[to[e]] = dep[u] + 1;
            Dep[to[e]] = Dep[u] + dist[e];
            build(to[e]);
            list[++cl] = u;
        }
        R[u] = clo;
        return ;
    }
    int Log[maxm], Lca[maxlog][maxm];
    void rmq_init() {
        Log[1] = 0;
        for(int i = 2; i <= cl; i++) Log[i] = Log[i>>1] + 1;
        for(int i = 1; i <= cl; i++) Lca[0][i] = list[i];
        for(int j = 1; (1 << j) <= cl; j++)
            for(int i = 1; i + (1 << j) - 1 <= cl; i++) {
                int a = Lca[j-1][i], b = Lca[j-1][i+(1<<j-1)];
                Lca[j][i] = dep[a] < dep[b] ? a : b;
            }
        return ;
    }
    int lca(int a, int b) {
        int l = min(pos[a], pos[b]), r = max(pos[a], pos[b]), t = Log[r-l+1];
        a = Lca[t][l]; b = Lca[t][r-(1<<t)+1];
        return dep[a] < dep[b] ? a : b;
    }
    int calc(int a, int b) {
        return Dep[a] + Dep[b] - (Dep[lca(a,b)] << 1);
    }
    int calcmx(int a, int b) {
        if(dep[a] < dep[b]) swap(a, b);
        int Mx = 0;
        for(int i = maxlog-1; i >= 0; i--) if(dep[a] - (1 << i) >= dep[b])
            Mx = max(Mx, mx[i][a]), a = fa[i][a];
        for(int i = maxlog-1; i >= 0; i--) if(fa[i][a] != fa[i][b])
            Mx = max(Mx, max(mx[i][a], mx[i][b])),
            a = fa[i][a], b = fa[i][b];
        return a == b ? Mx : max(Mx, max(mx[0][a], mx[0][b]));
    }
     
    bool cmp(int a, int b) { return dep[a] > dep[b]; }
    bool isson(int pa, int son) { return L[pa] <= L[son] && L[son] <= R[pa]; }
    bool on(int u, int pa, int son) { return isson(u, son) & isson(pa, u); }
     
    int main() {
        n = read(); q = read();
        for(int i = 1; i < n; i++) {
            int a = read(), b = read(), c = read();
            AddEdge(a, b, c);
        }
        build(1); rmq_init();
        for(int i = 1; i <= q; i++) {
            int u = read(), v = read();
            qs[i] = Que(u, v, calc(u, v));
    	}
    	sort(qs + 1, qs + q + 1);
    //	for(int i = 1; i <= q; i++) printf("%d %d %d %d
    ", qs[i].a, qs[i].b, qs[i].d, lca(qs[i].a, qs[i].b));
    	int A = qs[1].a, B = qs[1].b, ans = qs[1].d;
    //	printf("%d %d(%d %d)
    ", qs[2].d, calcmx(A, B), A, B);
    	if(qs[1].d != qs[2].d || q == 1)
    		ans = min(ans, max(qs[2].d, qs[1].d - calcmx(A, B)));
    	for(int i = 2; i <= q; i++) {
    		int a = qs[i].a, b = qs[i].b;
    		int a1 = a, b1 = b, c1 = lca(a1, b1), a2 = A, b2 = B, c2 = lca(a2, b2);
    		if((on(a2, c1, a1) && a2 != c1) || (on(b2, c1, a1) && b2 != c1) || (on(c2, c1, a1) && c2 != a1)
    		|| (on(a2, c1, b1) && a2 != c1) || (on(b2, c1, b1) && b2 != c1) || (on(c2, c1, b1) && c2 != b1)
    		|| (on(a1, c2, a2) && a1 != c2) || (on(b1, c2, a2) && b1 != c2) || (on(c1, c2, a2) && c1 != a2)
    		|| (on(a1, c2, b2) && a1 != c2) || (on(b1, c2, b2) && b1 != c2) || (on(c1, c2, b2) && c1 != b2)) ;
    		else break;
    		int ps[10];
    		ps[1] = lca(a, A); ps[2] = lca(a, B); ps[3] = lca(a, b);
    		ps[4] = lca(b, A); ps[5] = lca(b, B); ps[6] = lca(A, B);
    		sort(ps + 1, ps + 7, cmp);
    		int cp = unique(ps + 1, ps + 7) - ps;
    		A = ps[1]; B = ps[2];
    		bool ok = 1;
    		for(int j = 3; j <= cp; j++)
    			if(!isson(ps[j], A) || !isson(ps[j], B)) {
    				ok = 0; break;
    			}
    		if(!ok) break;
    		if(qs[i].d != qs[i+1].d || i == q)
    			ans = min(ans, max(qs[i+1].d, qs[1].d - calcmx(A, B)));
    		if(qs[i].d != qs[i+1].d || i == q)
    			ans = min(ans, max(qs[i+1].d, qs[1].d - calcmx(A, B)));
    //		printf("[%d %d]
    ", A, B);
        }
         
        printf("%d
    ", ans);
         
        return 0;
    }
    
  • 相关阅读:
    自定判断代码的执行环境
    将某个Qt4项目升级到Qt5遇到的问题[转]
    QT 智能提示设置
    c++基础 explicit
    Qt 5.2 Creator 和 vs2012 QT 插件的安装
    servlet乱码问题总结
    c++基础 使用智能指针
    Servlet学习之web服务器Tomcat 详解
    Windows数据类型
    友元类
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6002070.html
Copyright © 2020-2023  润新知