货车运输 洛谷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\)

数据范围:

对于 $ 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\)

样例

样例一输入:

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

样例一输出:

3
-1
3

思路

1.倍增,最小(da)生成树

显然,所有的车走过的路径,构成了一颗树
因为题目要求最小值最大
所以对原图构造最大生成树
然后在树上跑lca,倍增维护一下最小值就可以了
还有就是注意当两点不在一个联通块内判无解

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <list>
#include <map>

#define ll long long
#define ull unsigned long long

using namespace std;

const int mx_n = 101000;
int n,m,q;
int dep[mx_n];
int bcj[mx_n];
int fa[mx_n][20],le[mx_n][20];
int h[mx_n],to[mx_n<<1],nx[mx_n<<1],w[mx_n<<1],cnt;

struct stu {
    int u,v;
    int le;
    bool operator < (const stu&a)const {
        return le > a.le;
    }
} arr[501000];

inline void add(int f,int t,int co) {
    nx[++cnt] = h[f]; h[f] = cnt; to[cnt] = t; w[cnt] = co;
    nx[++cnt] = h[t]; h[t] = cnt; to[cnt] = f; w[cnt] = co;
}

int f(int x) {
    return bcj[x] == x ? x : bcj[x] = f(bcj[x]);
}

void dfs(int x) {
    for(int i = h[x]; i; i = nx[i])
        if(to[i] != fa[x][0]) {
            fa[to[i]][0] = x;
            le[to[i]][0] = w[i];
            dep[to[i]] = dep[x] + 1;
            dfs(to[i]);
        }
}

int LCA(int x,int y) {
    if(f(x) != f(y)) return -1;
    int mn = 0x3f3f3f3f;
    if(dep[x] < dep[y]) swap(x,y);
    for(int i = 19; i >= 0; i--)
        if(dep[fa[x][i]] >= dep[y]) {
            mn = min(mn,le[x][i]);
            x = fa[x][i];
        }
    if(x == y) return mn;
    for(int i = 19; i >= 0; i--)
        if(fa[x][i] != fa[y][i]) {
            mn = min(mn,min(le[x][i],le[y][i]));
            x = fa[x][i];
            y = fa[y][i];
        }
    return min(mn,min(le[x][0],le[y][0]));
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++) bcj[i] = i;
    for(int i = 1; i <= m; i++)
        scanf("%d%d%d",&arr[i].u,&arr[i].v,&arr[i].le);
    sort(arr+1,arr+1+m);
    for(int i = 1; i <= m; i++) {
        int u = arr[i].u;
        int v = arr[i].v;
        int co = arr[i].le;
        if(f(bcj[u]) != f(bcj[v])) {
            bcj[f(u)] = f(v);
            add(u,v,co);
        }
    }
    for(int i = 1; i <= n; i++)
        if(!dep[i]) {
            dep[i] = 1;
            dfs(i);
        }
    for(int i = 1; i <=19; i++)
        for(int j = 1; j <= n; j++) {
            fa[j][i] = fa[fa[j][i-1]][i-1];
            le[j][i] = min(le[j][i-1],le[fa[j][i-1]][i-1]);
        }
    int x,y;
    scanf("%d",&q);
    for(int i = 1; i <= q; i++) {
        scanf("%d%d",&x,&y);
        printf("%d\n",LCA(x,y));
    }
}
posted @ 2018-10-28 18:30  ullio  阅读(87)  评论(0编辑  收藏  举报