zoukankan      html  css  js  c++  java
  • 火车运输(最大生成树+lca) 洛谷P1967

    货车运输

    题目描述

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

    输入格式

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

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

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

    接下来 (q) 行,每行两个整数 (x,y) ,之间用一个空格隔开,表示一辆货车需要从 (x) 城市运输货物到 (y) 城市,保证 (x≠y)

    输出格式

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

    输入输出样例

    输入

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

    输出

    3
    -1
    3
    

    说明/提示

    对于 (30%) 的数据, (1≤n<1000,1≤m<10000,1≤q<1000)
    对于 (60%) 的数据, (1≤n<1000,1≤m<5×10^4,1≤q<1000)
    对于 (100%) 的数据, (1≤n<10^4,1≤m<5×10^4,1≤q<3×10^4,0≤z≤10^5)

    思路

    这道题思路并不难想,最大生成树加上lca,首先把跑一遍kruskal,建一个最大生成树,然后再用lca求最近公共祖先,再搜一遍很简单就可以求出来最小的承重,直接上代码吧。

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e4+10;
    
    struct Edge{//前向星
        int to,nxt,val,fro;
        bool operator <(const Edge &A)const{
            return val>A.val;
        }
    }E[10*N],e[10*N];
    
    int h[N],idx;
    
    void Ins(int a,int b,int c){//建边
        e[++idx].to = b; e[idx].nxt = h[a];h[a] = idx;e[idx].val = c;
    }
    
    int n,m;
    int f[N];
    
    int find(int x){//求祖先
        return f[x] == x ? x: (f[x] = find(f[x]));
    }
    
    void Kruskal(){//建最大生成树
        sort(E+1, E+m+1);
        for(int i = 1; i <= n; i++)
            f[i] = i;
        for(int i = 1; i <= m; i++){
            int u = E[i].fro,v = E[i].to,w = E[i].val;
            if(find(u) != find(v)){
                f[find(u)] = find(v);Ins(u,v,w);Ins(v,u,w);
            }
        }
    }
    
    int p[N][30],dep[N],Min[N][30];
    
    void dfs(int x){//搜索
        for(int i = 0; p[x][i]; i++){
            p[x][i+1] = p[p[x][i]][i];
            Min[x][i+1] = min(Min[x][i],Min[p[x][i]][i]);
        }
        for(int i = h[x]; i; i = e[i].nxt){
            int v = e[i].to;
            if(v == p[x][0]) continue;
            dep[v] = dep[x]+1;
            p[v][0] = x;
            Min[v][0] = e[i].val;
            dfs(v);
        }
    }
    
    int lca(int x,int y){//求最近公共祖先
        if(find(x) != find(y)) return -1;
        if(dep[x] < dep[y]) swap(x,y);
        int d = dep[x] - dep[y];
        int res = 0x7f7f7f7f;
        for(int i = 0; d; i++ , d >>= 1){
            if(d & 1){
                res = min(res, Min[x][i]);
                x = p[x][i];
            }
        }
        if(x == y) return res;
        for(int i = 24; i >= 0; i--){
            if(p[x][i] != p[y][i]){
                res = min(res, min(Min[x][i], Min[y][i]));
                x = p[x][i];y = p[y][i];
            }
        }
        res = min(res, min( Min[x][0], Min[y][0] ) );
        return res;
    }
    
    int main(){
        memset(Min, 0x7f, sizeof(Min));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++)
            scanf("%d%d%d", &E[i].fro, &E[i].to, &E[i].val);
        Kruskal();
        int q;
        scanf("%d", &q);
        for(int i = 1; i <= n; i++)
            if(! dep[i]) dfs(i);
        while(q--){
            int a,b;
            scanf("%d%d", &a, &b);
            printf("%d
    ", lca(a,b));
        }
    }
    

    代码并不是很难写,并不过多解释了。

  • 相关阅读:
    Python 的 Pandas 对矩阵的行进行求和
    python 统计字符串中指定字符出现次数的方法
    Python 2 代码转 Python 3的一些转化
    Python 的文件保存路径
    Pycharm 个人认为舒服漂亮又好用的主题风格
    【RS】Collaborative Memory Network for Recommendation Systems
    MATLAB 条形图添加多个图例
    MATLAB 画柱状图(/直方图)修改横坐标名称并使其横着显示
    Nexus3.X 将Maven项目上传至nexus私服
    nexus maven 使用案例
  • 原文地址:https://www.cnblogs.com/hzoi-liujiahui/p/13205133.html
Copyright © 2011-2022 走看看