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;
}
}