GYM 101889I(mst+lca)

最小生成树上倍增询问裸的。

const int maxn = 2e5 + 5;
int n, m, q;
//图
struct Edge {
	int u, v;
	ll cost;

	bool operator < (const Edge &rhs) const {
		return cost < rhs.cost;
	}
}e[maxn];
map<P, ll> mp;
//最小生成树
int fa[maxn];
vector<int> vc[maxn];
ll mst;
//树上倍增
int f[maxn][20], T, d[maxn];
ll dis[maxn][20];

int getf(int v) {
	return v == fa[v] ? v : fa[v] = getf(fa[v]);
}

void kruscal() {
	rep(i, 1, n)	fa[i] = i;
	sort(e + 1, e + 1 + m);

	rep(i, 1, m) {
		int t = getf(e[i].u), p = getf(e[i].v);
		if (t != p) {
			int u = e[i].u, v = e[i].v;
			vc[u].push_back(v);
			vc[v].push_back(u);
			mst += e[i].cost;
			fa[t] = p;
		}
	}
}

void bfs() {
	T = (int)(log(n) / log(2)) + 1;
	queue<int> Q;
	Q.push(1), d[1] = 1;

	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (auto y : vc[x]) {
			if (d[y])	continue;

			Q.push(y);
			f[y][0] = x;
			d[y] = d[x] + 1;
			dis[y][0] = mp[P(y, x)];

			rep(i, 1, T) {
				f[y][i] = f[f[y][i - 1]][i - 1];
				dis[y][i] = max(dis[f[y][i - 1]][i - 1], dis[y][i - 1]);
			}
		}
	}
}

ll lca(int x, int y) {
	ll ret = 0;
	if (d[x] > d[y])	swap(x, y);

	irep(i, T, 0)
		if (d[f[y][i]] >= d[x]) {
			ret = max(ret, dis[y][i]);
			y = f[y][i];
		}

	if (x == y)	return ret;

	irep(i, T, 0)
		if (f[y][i] != f[x][i]) {
			ret = max(ret, max(dis[y][i], dis[x][i]));
			y = f[y][i], x = f[x][i];
		}

	return max(ret, max(dis[y][0], dis[x][0]));
}

int main() {
	read(n), read(m);
	rep(i, 1, m) {
		read(e[i].u);
		read(e[i].v);
		read(e[i].cost);
		mp[P(e[i].u, e[i].v)] = mp[P(e[i].v, e[i].u)] = e[i].cost;
	}

	kruscal();
	bfs();
	
	for (read(q); q; q--) {
		int u, v;
		read(u), read(v);
		writeln(mst - lca(u, v) + mp[P(u, v)]);
	}
	return 0;
}
posted @ 2019-04-08 22:21  AlphaWA  阅读(156)  评论(0编辑  收藏  举报