【Gym - 101889I Imperial roads】【最小生成树+最近公共祖先】

【链接】:

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



*/

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/82349663