题目链接:https://vjudge.net/problem/Gym-101889I
题意:n个点,m条边,q次询问,每次必须选一边,求最小生成树的权值
题解:我们先跑一边最小生成树,然后按照最小边建树,必选某条边的话,如果在树上,那就直接输出,如果不在,那么在树上加上这条边肯定会形成一个环,那就在环中去掉一条权值最大的,那么路径查询树剖一下即可
#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
const int N = 1e5 + 10;
struct edge {
int x, y, z;
bool operator <(const edge &xx)const {
return z < xx.z;
}
}e[N * 2];
struct node {
int l, r;
int maxx;
}tree[N << 2];
map<pair<int, int>, int> mp;
vector<pair<int, int> > v[N];
int n, m, q;
int f[N];
int in[N], p[N], son[N], snum[N];
int dep[N], root[N], ff[N];
int val[N];
int tot;
int fath(int x) {
return x == f[x] ? f[x] : f[x] = fath(f[x]);
}
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
ff[u] = fa;
snum[u] = 1;
int to, z;
for(int i = 0; i < v[u].size(); i++) {
to = v[u][i].first;
z = v[u][i].second;
if(to == fa) continue;
dfs(to, u);
val[to] = val[u] + z;
snum[u] += son[to];
if(snum[son[u]] < snum[to])
son[u] = to;
}
}
void dfs1(int u, int fa, int rt) {
in[u] = ++tot;
p[tot] = u;
root[u] = rt;
if(son[u]) dfs1(son[u], u, rt);
int to;
for(int i = 0; i < v[u].size(); i++) {
to = v[u][i].first;
if(to == fa || to == son[u]) continue;
dfs1(to, u, to);
}
}
void build(int l, int r, int cur) {
tree[cur].l = l;
tree[cur].r = r;
if(l == r) {
tree[cur].maxx = val[p[l]];
return;
}
int mid = (l + r) >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
tree[cur].maxx = max(tree[cur << 1].maxx, tree[cur << 1 | 1].maxx);
}
int query(int pl, int pr, int cur) {
if(pl <= tree[cur].l && tree[cur].r <= pr) {
return tree[cur].maxx;
}
int res = 0;
if(pl <= tree[cur << 1].r) res = max(res, query(pl, pr, cur << 1));
if(pr >= tree[cur << 1 | 1].l) res = max(res, query(pl, pr, cur << 1 | 1));
return res;
}
int solve(int x, int y) {
int fx = root[x], fy = root[y];
int res = 0;
while(fx != fy) {
if(dep[fx] < dep[fy]) {
swap(x, y);
swap(fx, fy);
}
res = max(res, query(in[fx], in[x], 1));
x = ff[fx];
fx = root[x];
}
if(dep[x] > dep[y]) swap(x, y);
if(in[x] < in[y]) res = max(res, query(in[x] + 1, in[y], 1));
return res;
}
int main() {
int ans;
int x, y;
int xx, yy;
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d %d %d", &e[i].x, &e[i].y, &e[i].z);
mp[make_pair(e[i].x, e[i].y)] = e[i].z;
}
sort(e + 1, e + 1 + m);
ans = 0;
for(int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= m; i++) {
xx = fath(e[i].x);
yy = fath(e[i].y);
if(xx == yy) continue;
f[xx] = yy;
ans += e[i].z;
v[e[i].x].push_back(make_pair(e[i].y, e[i].z));
v[e[i].y].push_back(make_pair(e[i].x, e[i].z));
mp[make_pair(e[i].x, e[i].y)] = -1;
}
dfs(1, 0);
dfs1(1, 0, 1);
build(1, n, 1);
scanf("%d", &q);
while(q--) {
scanf("%d %d", &x, &y);
if(mp[make_pair(x, y)] == -1) printf("%d\n", ans);
else {
printf("%d\n", ans - solve(x, y) + mp[make_pair(x, y)]);
}
}
return 0;
}
转载:https://blog.csdn.net/mmk27_word/article/details/102075569
查看评论