CF891C Envy

题面

题解

首先要知道两个性质:

  1. 对于任意权值,最小生成树上该权值的边数是相同的。
  2. 对于任意一个最小生成树,当加完所有权值小于一个任意值的边之后,当前图的连通性是一样的。

于是我们按照权值分开处理,对每一种边的权值的每一个询问都处理一遍即可,这个可以写一个到撤销操作的并查集。

于是这道题目就做完了。

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<vector>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while(ch != '-' && (!isdigit(ch))) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(5e5 + 10);
struct edge { int x, y, w; } e[maxn];
struct qry { int id, x, y, w; };
inline int cmp(const edge &lhs, const edge &rhs) { return lhs.w < rhs.w; }
std::vector<qry> Q[maxn];
int fa[maxn], size[maxn], ans[maxn], n, m, q, stk[maxn], top;
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
inline int merge(int x, int y)
{
	x = find(x), y = find(y);
	if(x == y) return 0;
	if(size[x] > size[y]) std::swap(x, y);
	fa[x] = y, size[y] += size[x], stk[++top] = x;
	return 1;
}

int main()
{
	n = read(), m = read();
	for(RG int i = 1; i <= m; i++)
		e[i] = (edge) {read(), read(), read()};
	q = read();
	for(RG int i = 1, k; i <= q; i++)
	{
		k = read();
		for(RG int j = 1, x; j <= k; j++)
			x = read(), Q[e[x].w].push_back((qry) {i, e[x].x, e[x].y, e[x].w});
	}
	std::sort(e + 1, e + m + 1, cmp);
	for(RG int i = 1; i <= n; i++) size[fa[i] = i] = 1;
	for(RG int i = 1; i <= q; i++) ans[i] = 1;
	for(RG int i = 1; i <= m; i++)
	{
		int val = e[i].w; top = 0;
		for(RG int j = 0; j < (int)Q[val].size(); j++)
		{
			if(!ans[Q[val][j].id]) continue;
			if(j > 0 && Q[val][j].id != Q[val][j - 1].id)
				while(top)
				{
					int x = stk[top--];
					size[fa[x]] -= size[x];
					fa[x] = x;
				}
			if(!merge(Q[val][j].x, Q[val][j].y))
				ans[Q[val][j].id] = 0;
		}
		while(e[i].w == val) merge(e[i].x, e[i].y), ++i;
		if(e[i].w != val) --i;
	}
	for(RG int i = 1; i <= q; i++) puts(ans[i] ? "YES" : "NO");
	return 0;
}
原文地址:https://www.cnblogs.com/cj-xxz/p/10456493.html