899 字
4 分钟
P1967 [NOIP2013 提高组] 货车运输
题目
货车运输
A 国有 座城市,编号从 到 ,城市之间有 条双向道路。每一条道路对车辆都有重量限制,简称限重。
现在有 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入格式
第一行有两个用一个空格隔开的整数 ,表示 A 国有 座城市和 条道路。
接下来 行每行三个整数 ,每两个整数之间用一个空格隔开,表示从 号城市到 号城市有一条限重为 的道路。 注意: ,两座城市之间可能有多条道路 。
接下来一行有一个整数 ,表示有 辆货车需要运货。
接下来 行,每行两个整数 ,之间用一个空格隔开,表示一辆货车需要从 城市运输货物到 城市,保证
对于 的数据,,,,。
题解
由于要求路径上的最小值最大,所以 二分(当然可以,但我不会QAQ) 求出最大生成树来,然后对于每次询问的两点lca查询路径上的最小值即可
具体实现和lca差不多
问题
1.建双向边
2.并查集fa[/*!!!*/x_fa] = y;
3.125行取min写成了anc
代码
#include<bits/stdc++.h> using namespace std;
int read() { int f = 1, x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return f * x; }
const int N = 1e4 + 10, M = 1e5 + 100;
struct U { int x, y, z; bool operator < (const U o) const { return z > o.z; } }u[M >> 1]; int cnt = 1;
int fa[N], n, m;
int anc[N][20], path_min[N][20], depth[N];
int getfa(int u) { if(fa[u] == u) return u; return fa[u] = getfa(fa[u]); }
void merge(int x, int y) { int x_fa = getfa(x), y_fa = getfa(y); fa[/*!!!*/x_fa] = y; }
int head[N], nxt[M], to[M], edge[M], tot = 1;
void add(int x, int y, int z) { to[++tot] = y; edge[tot] = z; nxt[tot] = head[x]; head[x] = tot; }
void dfs(int u, int fa) { depth[u] = depth[fa] + 1; anc[u][0] = fa; for(int i = head[u]; i; i = nxt[i]) { int v = to[i]; if(v == fa) continue; path_min[v][0] = edge[i]; dfs(v, u); } }
void lca_init() { for(int j = 1;j < 20;j++) { for(int i = 1;i <= n;i++) { anc[i][j] = anc[anc[i][j - 1]][j - 1]; path_min[i][j] = min(path_min[i][j - 1], path_min[anc[i][j - 1]][j - 1]); } } }
int lca_query_anc(int x, int y) { if(depth[x] < depth[y]) swap(x, y); for(int i = 19;i >= 0;i--) { if(depth[anc[x][i]] >= depth[y]) x = anc[x][i]; }
if(x == y) return x;
for(int i = 19;i >= 0;i--) { if(anc[x][i] != anc[y][i]) x = anc[x][i], y = anc[y][i]; } return anc[x][0]; }
int lca_query_min(int x, int y) { int ans = 0x3f3f3f3f; if(depth[x] < depth[y]) swap(x, y); for(int i = 19;i >= 0;i--) { if(depth[anc[x][i]] >= depth[y]) { ans = min(ans, path_min[x][i]); x = anc[x][i]; } } if(x == y) return ans; for(int i = 19;i >= 0;i--) { if(anc[x][i] != anc[y][i]) { ans = min(ans, path_min[x][i]), ans = min(ans, path_min[y][i]); x = anc[x][i], y = anc[y][i]; } } return min(ans, min(path_min[x][0], path_min[y][0])); }
int main() { n = read(), m = read(); for(int i = 1;i <= n;i++) { fa[i] = i; }
int x, y, z; for(int i = 1;i <= m;i++) { x = read(), y = read(), z = read(); u[cnt].x = x; u[cnt].y = y, u[cnt].z = z; ++cnt; }
sort(u + 1, u + 1 + m);
for(int i = 1;i <= m;i++) { int x_fa = getfa(u[i].x), y_fa = getfa(u[i].y); if(x_fa != y_fa) { merge(u[i].x, u[i].y); add(u[i].x, u[i].y, u[i].z); add(u[i].y, u[i].x, u[i].z); } }
for(int i = 1;i <= n;i++) { if(fa[i] == i) { dfs(i, 0); } } lca_init(); int q; q = read();
// for(int i = 1;i <= n;i++)// {// cout << "qwq "<<path_min[i][2] << endl;// }
while(q--) { x = read(), y = read(); int x_fa = getfa(x), y_fa = getfa(y); if(x_fa != y_fa) { printf("-1\n"); continue; } cout << lca_query_min(x, y) << endl; }
}
P1967 [NOIP2013 提高组] 货车运输
https://blog.histcat.top/posts/p1967/