【链接】:
http://codeforces.com/gym/101889/attachments
【题意】:
给出一条边,求含这条边的最小生成树
【思路】:
先求出原图中的最小生成树。
若边在生成树中,则没有影响。否则,加上这条边减去最小生成树上两点间的最大点权
【代码】:
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int maxn = 2e5 + 6;
map<pii, int>mp, vis;
vector<pii>v[maxn];
int f[maxn][20], father[maxn], ma[maxn][20], in[maxn], d[maxn];
int root, ans, maxv = 0, t;
struct node {
int x, y, w;
bool operator <(const node &r) const {
return w > r.w;
}
}k[maxn];
priority_queue<node>q;
int find(int x) { return x == father[x] ? x : father[x] = find(father[x]); }
void bfs() {
queue<int>qu;
qu.push(root);
d[root] = 1;
while (qu.size()) {
int x = qu.front(); qu.pop();
for (auto y : v[x]) {
int nt = y.first;
int vv = y.second;
if (d[nt])continue;
d[nt] = d[x] + 1;
f[nt][0] = x;
ma[nt][0] = vv;
for (int i = 1; i <= t; i++) {
f[nt][i] = f[f[nt][i - 1]][i - 1];
ma[nt][i] = max(ma[nt][i - 1], ma[f[nt][i - 1]][i - 1]);
}
qu.push(nt);
}
}
}
void lca(int x, int y) {
if (d[x] > d[y])swap(x, y);
for (int i = t; i >= 0; i--)
if (d[f[y][i]] >= d[x]) {
maxv = max(maxv, ma[y][i]); y = f[y][i];
}
if (x == y) {
return;
}
for (int i = t; i >= 0; i--)
if (f[x][i] != f[y][i]) {
maxv = max(maxv, ma[x][i]); x = f[x][i];
maxv = max(maxv, ma[y][i]); y = f[y][i];
}
maxv = max(maxv, max(ma[x][0], ma[y][0]));
return;
}
void kruskal(void) {
while (q.size()) {
node tmp = q.top(); q.pop();
int fx = find(tmp.x);
int fy = find(tmp.y);
if (fx == fy) { continue; }
else {
father[fx] = fy;
v[tmp.x].push_back({ tmp.y,tmp.w });
v[tmp.y].push_back({ tmp.x,tmp.w });
vis[pii(tmp.x, tmp.y)] = vis[pii(tmp.y, tmp.x)] = 1;
root = tmp.x;
ans += tmp.w;
}
}
}
int main() {
int N, R;
scanf("%d%d", &N, &R);
t = (int)(log(N) / log(2)) + 1;
for (int i = 1; i <= N; i++) {
father[i] = i;
}
while (R--) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
mp.insert({ make_pair(x,y),z });
mp.insert({ make_pair(y,x),z });
q.push(node{ x,y,z });
}
kruskal();
bfs();
int q;
scanf("%d", &q);
while (q--) {
int x, y;
scanf("%d%d", &x, &y);
if (vis[pii(x, y)]) {
printf("%d\n", ans);
}
else {
maxv = 0;
lca(x, y);
printf("%d\n", ans + mp[pii(x, y)] - maxv);
}
}
}
/*
3 3
1 2 10
2 3 5
1 3 7
3
2 3
1 2
1 3
4 4
1 2 1
2 4 1
2 3 100
1 4 50
1
1 4
*/