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));
        }
    }
    

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

  • 相关阅读:
    cocos2d-x 3.0rc开发指南:Windows下Android环境搭建
    CSS 最核心的几个概念
    android CMWAP, CMNET有何差别
    JAVA读、写EXCEL文件
    freemarker报错之三
    “大型票务系统”和“实物电商系统”在支付方面的差别和联系
    C++内存泄露检測原理
    递归算法浅谈
    自写图片遮罩层放大功能jquery插件源代码,photobox.js 1.0版,不兼容IE6
    linux 之 getopt_long()
  • 原文地址:https://www.cnblogs.com/hzoi-liujiahui/p/13205133.html
Copyright © 2011-2022 走看看