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