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
原文地址:https://www.cnblogs.com/de-compass/p/11869774.html