• NOIP2013 | 货车运输


    Description

      A国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    Input

      第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

      接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。

      接下来一行有一个整数 q,表示有 q 辆货车需要运货。

      接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

    Output

      输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

    Sample Input 1 

    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3

    Sample Output 1

    3
    -1
    3

    Hint

    对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;
    对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;
    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

    Kruskal构建最大生成树,要经过的边一定在这棵树上(可用反证法证明)
    之后LCA处理询问即可
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn = 10005, maxm = 50005, inf = 0x3f3f3f3f;
    
    struct edge{
        int a, b, w;
        bool operator <(const edge& b) const { return w>b.w; }
    } e[maxm];
    
    int fir[maxn], ne[maxn*2], to[maxn*2], w[maxn*2], np;
    void add(int x, int y, int z) {
        ne[++np] = fir[x];
        fir[x] = np;
        to[np] = y;
        w[np] = z;
    }
    
    int fa[maxn];
    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
    
    int n, m;
    
    void kruskal() {
        sort(e, e+m);
        for(int i=0; i<m; i++) {
            int u = e[i].a, v = e[i].b;
            if(find(u) == find(v)) continue;
            fa[find(u)] = find(v);
            add(u, v, e[i].w);
            add(v, u, e[i].w);
        }
    }
    
    int f[maxn][20], dist[maxn][20];
    int dep[maxn];
    void dfs(int u, int F, int depth, int wf) {
        dep[u] = depth;
        f[u][0] = F; dist[u][0] = wf;
        for(int i=1; i<=18; i++)
            f[u][i] = f[f[u][i-1]][i-1],
            dist[u][i] = min( dist[u][i-1], dist[f[u][i-1]][i-1]);
        for(int i=fir[u]; i; i=ne[i])
            if(to[i] != F)
                dfs(to[i], u, depth+1, w[i]);
    }
    
    int LCA(int x, int y) {
        if(find(x) != find(y)) return -1;
        if(dep[x]<dep[y]) swap(x, y);
        int ans = inf;
        for(int i=18; i>=0; i--)
            if((dep[x]-dep[y])&(1<<i)) {
                ans = min(ans, dist[x][i]);
                x = f[x][i];
            }
        if(x == y) return ans;
        for(int i=18; i>=0; i--)
            if(f[x][i] != f[y][i]) {
                ans = min(ans, min(dist[x][i], dist[y][i]));
                x = f[x][i];
                y = f[y][i];
            }
        return min(ans, min(dist[x][0], dist[y][0]));
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++) fa[i] = i;
        for(int i=0, x, y, z; i<m ;i++) {
            scanf("%d%d%d", &x, &y, &z);
            e[i]=(edge){x, y, z};
        }
        kruskal();
        for(int i=1; i<=n; i++)
            if(!dep[i])
                dfs(i, 0, 1, inf);
        int q;
        scanf("%d", &q);
        while(q--){
            int x, y;
            scanf("%d%d", &x, &y);
            printf("%d
    ", LCA(x, y));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    14.6.1 Creating InnoDB Tables 创建InnoDB 表:
    mysql iot 主键自增列问题
    mysql iot 主键自增列问题
    perl 定义post接口
    perl 定义post接口
    [置顶] 一步步构建大型网站架构
    [置顶] 一步步构建大型网站架构
    技术人员如何面试
    技术人员如何面试
    技术人员如何面试
  • 原文地址:https://www.cnblogs.com/de-compass/p/11869774.html
Copyright © 2020-2023  润新知