CF1166F - Vicky's Delivery Service(并查集,启发式合并)

给出节点数为\(n\),边数为\(m\)的图。

保证每个点对都是互连的。

定义彩虹路:这条路经过\(k\)个节点,对于\(x(x\%2=0)\)的节点,左右两条边颜色相同。

现在有\(q\)次操作。

第一种操作是添加一条边。

第二种操作是回答是否能经过彩虹边从\(a\)节点到达\(b\)节点。

做法:

能相互到达的点用并查集连起来。

具体做法就是:

当\(a-b-c\)的边的颜色相同时,我们把\(a\)和\(c\)节点用合并,代表\(a\)和\(c\)互连。

对于节点\(a\),每个颜色的边只需要保存一条,这样可以快速合并节点。

这里可以枚举b的边集,按序合并即可。

但是还有一种情况,\(x\)节点和\(y\)节点经过的边数为奇数,这样最后一条边的颜色就不重要了。

所以如果两个节点不在一个集合内,就需要看其中一个点能否通过另一个集合到达。

对每个集合维护一个set,然后枚举每条边,把这条边两端的节点塞进另一个节点的集合的set。

加边的时候,对边两边的节点维护并查集。

合并集合的时候,对集合对应的set,启发式合并即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,c,q;
map<int,int> g[maxn];
set<int> st[maxn];
int father[maxn];
int findfather (int x) {
	int a=x;
	while (x!=father[x]) x=father[x];
	while (a!=father[a]) {
		int z=a;
		a=father[a];
		father[z]=x;
	} 
	return x;
} 
void un (int x,int y) {
	x=findfather(x);
	y=findfather(y);
	if (x==y) return;
	if (st[x].size()<st[y].size()) {
		father[x]=y;
		for (auto it:st[x]) st[y].insert(it);
	}
	else {
		father[y]=x;
		for (auto it:st[y]) st[x].insert(it);
	}
}
int main () {
	scanf("%d%d%d%d",&n,&m,&c,&q);
	for (int i=1;i<=n;i++) father[i]=i;
	while (m--) {
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		st[findfather(y)].insert(x);
		st[findfather(x)].insert(y);
		if (g[x].count(z)) {
			un(g[x][z],y);
		}
		else {
			g[x][z]=y;
		}
		if (g[y].count(z)) {
			un(g[y][z],x);
		}
		else {
			g[y][z]=x;
		}
	}
	while (q--) {
		char op;
		getchar();
		scanf("%c",&op);
		if (op=='+') {
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			st[findfather(y)].insert(x);
			st[findfather(x)].insert(y);
			if (g[x].count(z)) {
				un(g[x][z],y);
			}
			else {
				g[x][z]=y;
			}
			if (g[y].count(z)) {
				un(g[y][z],x);
			}
			else {
				g[y][z]=x;
			}
		}
		else {
			int x,y;
			scanf("%d%d",&x,&y);
			if (findfather(x)==findfather(y)) {
				printf("Yes\n");
			}
			else if (st[findfather(x)].count(y)) {
				printf("Yes\n");
			}
//			else if (st[findfather(y)].count(x)) {
//				printf("Yes\n");
//			}
			else {
				printf("No\n");
			}
		}
	}
}
上一篇:CI /CD


下一篇:python设计模式(十七):迭代器模式——迭代器与生成器