• 洛谷 P1967 货车运输


          洛谷 P1967 货车运输

    题目描述

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

    输入输出格式

    输入格式:

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

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3
    输出样例#1: 复制
    3
    -1
    3

    说明

    对于 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 。

    思路:先求最小生成树,记录下最小生成树中权值最大的边,然后根据这条边再求最大生成树,然后通过求LCA求出最后的答案

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int n, m, q, x, y, cnt;
    int hd[10005], nxt[20005], to[20005], w[20005];
    int p[50005], f[10005][20], minv[10005][20], dep[10005];
    struct edge {
        int x, y, z;
        bool operator < (const edge &rhs) const {
            return z > rhs.z;
        }
    } e[50005];
    
    void add(int x, int y, int z) {
        to[cnt] = y;
        w[cnt] = z;
        nxt[cnt] = hd[x];
        hd[x] = cnt++;
    }
    
    int fnd(int x) {
        return p[x] == x ? x : p[x] = fnd(p[x]);
    }
    void kruskal() {
        for(int i = 0; i < m; i++) p[i] = i;
        sort(e, e+m);
        for(int i = 0; i < m; i++) if(fnd(e[i].x) != fnd(e[i].y)) {
                add(e[i].x, e[i].y, e[i].z);
                add(e[i].y, e[i].x, e[i].z);
                p[fnd(e[i].x)] = fnd(e[i].y);
            }
    }
    
    void dfs(int x, int p) {
        for(int i = hd[x]; ~i; i = nxt[i]) if(i != p) {
                dep[to[i]] = dep[x] + 1;
                f[to[i]][0] = x;
                minv[to[i]][0] = w[i];
                dfs(to[i], i ^ 1);
            }
    }
    
    int lca(int x, int y) {
        int ans = 100000000;
        if(dep[x] > dep[y]) swap(x, y);
        for(int i = 15; i >= 0; i--) if(dep[f[y][i]] >= dep[x]) {
                ans = min(ans, minv[y][i]);
                y = f[y][i];
            }
        if(x == y) return ans;
        for(int i = 15; i >= 0; i--) if(f[x][i] != f[y][i]) {
                ans = min(ans, min(minv[x][i], minv[y][i]));
                x = f[x][i];
                y = f[y][i];
            }
        return f[x][0] == 0 ? -1 : min(ans, min(minv[x][0], minv[y][0]));
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i++) scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
        memset(hd, -1, sizeof hd);
        kruskal();
        dep[1] = 1;
        dfs(1, -1);
        for(int j = 1; j <= 15; j++)
            for(int i = 1; i <= n; i++) {
                f[i][j] = f[f[i][j-1]][j-1];
                minv[i][j] = min(minv[i][j-1], minv[f[i][j-1]][j-1]);
            }
        scanf("%d", &q);
        while(q--) scanf("%d%d", &x, &y), printf("%d
    ", lca(x, y));
        return 0;
    }
    View Code
  • 相关阅读:
    常用SQL语句
    H5内嵌原生app
    github 从一个仓库换到另一个仓库
    vue使用install函数把组件做成插件方便全局调用
    git 支持tree命令
    vue---vue2.x自定义plugin,给vue添加全局方法,原型上增加全局方法
    vue 生命周期函数
    登录拦截设置白名单-坑
    vue
    vue实现滚动条滚到相应高度触发动画的操作
  • 原文地址:https://www.cnblogs.com/v-vip/p/9343181.html
Copyright © 2020-2023  润新知