题目链接:https://cn.vjudge.net/contest/257313#problem/I
和这道题类似:https://blog.csdn.net/GYH0730/article/details/82827285
先求出最小生成树来,如果必须要修的边在最小生成树上,直接输出最小生成树的值就行了,否则必须修的边肯定会和最小生成树上的边形成一个环,删掉这条环上的除了这条边以外的最大边就行了,问题就转化为求瓶颈路问题了,之前用朴素的LCA写的,交在这个题t了,改用倍增LCA了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
const int M = N << 2;
int n, m, head[N], mm;
int len[N];
struct Edge {
int to, next, w;
}e[N << 1];
struct EE {
int u, v, w;
}E[M];
bool cmp(EE a, EE b) { return a.w < b.w; }
void add(int u, int v, int w)
{
e[mm].to = v;
e[mm].w = w;
e[mm].next = head[u];
head[u] = mm++;
}
int sz[N], dep[N];
int f[N][22]; /// f[i][j] 表示 i 的第 2^j 个祖先
int dp[N][22];
void dfs(int u, int fa) /// 点从 1 开始标号
{
f[u][0] = fa;
sz[u] = 1;
for (int i=head[u];~i;i=e[i].next)
{
int v = e[i].to;
if (v != fa)
{
dep[v] = dep[u] + 1;
len[v] = len[u] + e[i].w;
dp[v][0] = e[i].w;
dfs(v, u);
sz[u] += sz[v];
}
}
}
int maxh;
void gao()
{
int j;
for (j=1;(1<<j)<n;j++)
for (int i=1;i<=n;i++)
{
int t = f[i][j-1];
f[i][j] = f[f[i][j-1]][j-1];
dp[i][j] = max(dp[i][j-1], dp[t][j-1]);
}
maxh = j - 1;
}
int swim(int x, int k, int &ma) /// 返回 x 的第 k 个祖先
{
ma = 0;
for (int i=0;i<=maxh;i++)
if (k >> i & 1)
{
ma = max(ma, dp[x][i]);
x = f[x][i];
}
return x;
}
int LCA(int x, int y)
{
if (dep[x] > dep[y]) swap(x, y); ///dep[x] <= dep[y];
int ans = 0;
y = swim(y, dep[y] - dep[x], ans);
if (x == y) return ans;
for (int i=maxh; i>=0; i--) {
if (f[x][i] != f[y][i])
{
ans = max(ans, max(dp[x][i], dp[y][i]));
x = f[x][i], y = f[y][i];
}
}
return max(ans, max(dp[x][0], dp[y][0]) ); //f[x][0];
}
int fa[N];
int find(int x) { return x==fa[x] ? x : fa[x]=find(fa[x]); }
map<int,int> mp1[N],mp2[N];
int main(void)
{
while (scanf("%d %d",&n,&m) != EOF) {
dep[1] = 0;
len[1] = 0;
dp[1][0] = 0;
int sum = 0;
for (int i=1;i<=n;i++) {
fa[i] = i;
mp1[i].clear();
mp2[i].clear();
}
mm = 0;
for (int i=0;i<m;i++) {
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
if(E[i].u > E[i].v) swap(E[i].u,E[i].v);
mp1[E[i].u][E[i].v] = E[i].w;
}
sort(E, E+m, cmp);
memset(head, -1, sizeof head);
int cnt = 0;
for (int i=0;i<m;i++) {
int a=find(E[i].u), b=find(E[i].v);
if (a - b) {
fa[a] = b;
add(E[i].u, E[i].v, E[i].w);
add(E[i].v, E[i].u, E[i].w);
mp2[E[i].u][E[i].v] = 1;
sum += E[i].w;
if (++cnt == n-1) break;
}
}
dfs(1, 0);
gao();
int Q;
scanf("%d", &Q);
while (Q--) {
int a, b;
scanf("%d%d",&a,&b);
if(a > b) swap(a,b);
if(mp2[a][b]) printf("%d\n",sum);
else {
int c = LCA(a, b);
printf("%d\n",sum - c + mp1[a][b]);
}
}
}
return 0;
}