题意简述
给定一张图,求两点最短路径上的点的值的最小值
题解思路
先进行最大生成树,再倍增求lca
代码
#include <cstdio>
#include <algorithm>
struct Edge
{
int u, v, w;
}e[51000];
int n, m, q, u, v, w, xx, yy, cnt;
int fa[11000];
int h[21000], to[21000], nxt[21000], val[21000];
int lg[21000], dep[21000], f[21000][20][2];
inline bool cmp(const Edge& x, const Edge& y) {return x.w > y.w; }
int find(const int& x) {return x ^ fa[x] ? fa[x] = find(fa[x]) : x; }
inline void add_edge(const int& u, const int& v, const int& w)
{
to[++cnt] = v;
val[cnt] = w;
nxt[cnt] = h[u];
h[u] = cnt;
}
void dfs(const int& x)
{
for (register int i = 0; f[x][i][0]; ++i)
{
f[x][i + 1][0] = f[f[x][i][0]][i][0];
f[x][i + 1][1] = std::min(f[x][i][1], f[f[x][i][0]][i][1]);
}
for (register int i = h[x]; i; i = nxt[i])
if (to[i] ^ f[x][0][0])
{
dep[to[i]] = dep[x] + 1;
f[to[i]][0][0] = x;
f[to[i]][0][1] = val[i];
dfs(to[i]);
}
}
inline int lca(int u, int v, int s = 0x3f3f3f3f)
{
if (dep[u] < dep[v]) std::swap(u, v);
while (dep[u] > dep[v])
{
s = std::min(s, f[u][lg[dep[u] - dep[v]]][1]);
u = f[u][lg[dep[u] - dep[v]]][0];
}
if (u == v) return s;
for (register int i = lg[dep[u]] + 1; i--; )
if (f[u][i][0] ^ f[v][i][0])
{
s = std::min(s, f[u][i][1]);
s = std::min(s, f[v][i][1]);
u = f[u][i][0];
v = f[v][i][0];
}
s = std::min(s, f[u][0][1]);
s = std::min(s, f[v][0][1]);
return s;
}
int main()
{
scanf("%d%d", &n, &m);
for (register int i = 1; i <= n; ++i) fa[i] = i;
for (register int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
for (register int i = 1; i <= m; ++i)
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
std::sort(e + 1, e + m + 1, cmp);
for (register int i = 1; i <= m; ++i)
{
xx = find(e[i].u);
yy = find(e[i].v);
if (xx != yy)
{
fa[xx] = yy;
add_edge(e[i].u, e[i].v, e[i].w);
add_edge(e[i].v, e[i].u, e[i].w);
}
}
for (register int i = 1; i <= n; ++i) if (!dep[i]) dfs(i);
scanf("%d", &q);
for (register int i = 1; i <= q; ++i)
{
scanf("%d%d", &u, &v);
if (find(u) != find(v)) printf("-1
");
else printf("%d
", lca(u, v));
}
}