题目描述

\(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\n", lca(a,b));
    }
}

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

相关文章:

  • 2022-01-14
  • 2021-09-26
  • 2021-11-09
  • 2022-01-20
  • 2022-02-12
  • 2022-12-23
  • 2021-05-19
  • 2022-12-23
猜你喜欢
  • 2021-06-13
  • 2022-01-05
  • 2022-02-01
  • 2022-12-23
  • 2021-10-21
  • 2022-02-08
  • 2022-01-20
相关资源
相似解决方案