题意:给定一个图,和 q 次查询,每次询问一条边,回答要使得这条边一定出现在任意最小生成树时它的权值最大可以修改到多少?
思路: 如果该边不在 MST 上,MST 上 u to v 的路径上的最大边权 - 1 即为它可以修改的最大边权 如果在,
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 5e5 + 10;
const int M = 2e6 + 10;
typedef long long ll;
typedef pair<int, int> pi;
int n, m;
struct edge {
int u, v, w, id;
bool operator < (edge x) const {
return w < x.w;
}
}e[M];
vector<edge> g[N], g2[N];
struct dsu {
int f[N], val[N];
void init () {
for (int i = 1; i <= n; i ++) f[i] = i;
}
int find (int x) {
return f[x] = (f[x] == x ? x : find(f[x]));
}
}d;
int son[N], dep[N], fath[N], dfn[N], top[N], siz[N], tmp, to[N], val[N];
int bel[N];
int fa[N][40], k;
void dfs1 (int u, int _fa) {
siz[u] = 1, fath[u] = _fa, dep[u] = dep[_fa] + 1;
fa[u][0] = _fa;
for (int i = 1; ; i ++) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
if(!fa[u][i]) {
k = max(k, i - 1);
break;
}
}
for (auto e : g[u]) {
int v = e.v;
if (v == _fa) continue;
val[v] = e.w, bel[e.id] = v;
dfs1 (v, u);
if (siz[v] > siz[son[u]]) son[u] = v;
siz[u] += siz[v];
}
}
int mi[N][40];
void modify (int u, int v, int val) {
if(dep[u] < dep[v]) swap(u, v);
for (int i = k; i >= 0; i --) {
if(dep[fa[u][i]] >= dep[v]) {
mi[u][i] = val;
u = fa[u][i];
}
}
if(u == v) return;
for (int i = k; i >= 0; i --) {
if(fa[u][i] != fa[v][i]) {
mi[u][i] = mi[v][i] = val;
u = fa[u][i], v = fa[v][i];
}
}
}
void pushdown () {
for (int i = k; i >= 1; i --) {
for (int j = 1; j <= n; j ++) {
if (!mi[j][i]) continue;
// cout << j << ' ' << i << ' ' << mi[j][i] << endl;
mi[j][i - 1] = min(mi[j][i - 1], mi[j][i]);
// cout << mi[j][i - 1] << endl;
mi[fa[j][i - 1]][i - 1] = min(mi[fa[j][i - 1]][i - 1], mi[j][i]);
}
}
}
void dfs2 (int u, int tp) {
top[u] = tp, dfn[u] = ++ tmp, to[tmp] = u;
if(son[u]) dfs2(son[u], tp);
for (auto e : g[u]) {
if (e.v == fath[u] || e.v == son[u]) continue;
dfs2 (e.v, e.v);
}
}
struct tree {
int ma[N][40];
#define mid (l + r >> 1)
#define ls p << 1, l, mid
#define rs (p << 1) | 1, mid + 1, r
void build() {
for (int i = 1; i <= n; i ++) ma[i][0] = val[to[i]];
for (int k = 1; (1 << k) <= n; k ++) {
for (int i = 1; i + (1 << k) - 1 <= n; i ++) {
ma[i][k] = max(ma[i][k - 1], ma[i + (1 << k - 1)][k - 1]);
}
}
}
int getmax (int ql, int qr) {
int len = log2(qr - ql + 1);
return max (ma[ql][len], ma[qr - (1 << len) + 1][len]);
}
}t;
int getmax (int u, int v) {
int res = 0;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
int tmp = t.getmax(dfn[top[u]], dfn[u]);
res = max(tmp, res);
u = fath[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
if (u == v) return res;
int tmp = t.getmax(dfn[v] + 1, dfn[u]);
res = max(res, tmp);
return res;
}
int dfth[N], low[N], idx;
bool mark[M], mk[M];
void tarjan (int u, int from) {
dfth[u] = low[u] = ++ idx;
for (auto e : g2[u]) {
int v = e.v;
if (!dfth[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfth[u]) mark[e.id] = 1;
} else if (v != from) low[u] = min(low[u], dfn[v]);
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++) d.f[i] = i;
for (int i = 1; i <= m; i ++) cin >> e[i].u >> e[i].v >> e[i].w, e[i].id = i;
sort (e + 1, e + 1 + m);
for (int i = 1; i <= m; i ++) {
int u = e[i].u, v = e[i].v;
if (d.find(u) != d.find(v)) {
d.f[d.find(u)] = d.find(v);
mk[e[i].id] = 1;
g[u].push_back({u, v, e[i].w, e[i].id});
g[v].push_back({v, u, e[i].w, e[i].id});
}
g2[u].push_back({u, v, e[i].w, e[i].id});
g2[v].push_back({v, u, e[i].w, e[i].id});
}
dfs1 (1, 0);
dfs2 (1, 1);
for (int i = 1; i <= n; i ++)
for (int j = 0; j <= k; j ++) mi[i][j] = 0x3f3f3f3f;
t.build();
for (int i = m; i >= 1; i --) {
if (!mk[e[i].id]) modify(e[i].u, e[i].v, e[i].w);
}
pushdown();
tarjan(1, 0);
int q;
sort (e + 1, e + 1 + m, [] (edge x, edge y) {
return x.id < y.id;
});
cin >> q;
while (q --) {
int id;
cin >> id;
if (mark[id]) cout << -1 << endl;
else {
if (mk[id]) {
int u = (dep[e[id].u] < dep[e[id].v] ? e[id].v : e[id].u);
int v = mi[u][0];
cout << v - 1 << endl;
} else {
cout << getmax(e[id].u, e[id].v) - 1 << endl;
}
}
}
return 0;
}