2020洛谷春季多校第二场E题--判断两图是否连通同构

题意:给两幅点数一样的图,然后q次询问,每次询问会在图A或图B内加一条边,问加边后的两图是否连通同构

1.题解的做法:先给每一个点一个随机值,然后若合并两个不在同一集合内的两点就把他们两个集合代表的随机值拿出来,再把他们两异或后的结果放回去,最后判断两个图的剩余的值和是不是相同

/*判断两无向图是否连通同构*/ 
#include 
#include  
#include 
#include 
using namespace std;
typedef unsigned long long ll;
const int N = 100010;
int n,m;
unordered_set<ll> G;
ll hh[N];
void add(ll x){
	if(G.count(x)) G.erase(x);
	else G.insert(x);
} 
struct UFS{
	int fa[N];
	ll H[N];
	void init(){
		for(int i = 1;i <= n;i++) fa[i] = i,H[i] = hh[i];
	}
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	void merge(int x,int y){
		int fx = find(x),fy = find(y);
		if(fx != fy){
			add(H[fx]);
			add(H[fy]);
			H[fx]^=H[fy];
			add(H[fx]);
			fa[fy] = fx;
		}
	}
}f[2];
mt19937_64 rnd(12312778312);///产生随机数 

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i++) hh[i] = rnd();
	f[0].init(),f[1].init();
	for(int i = 0;i < m;i++){
		int op,u,v;scanf("%d%d%d",&op,&u,&v);
		f[op-1].merge(u,v);
		if(G.size()) puts("B");
		else puts("A");
	} 
	return 0;
}

另外的做法,搞两个并查集

参考这位大佬

大佬的博客

#include 
using namespace std;
const int N = 1e5+10;
int fa1[N],fa2[N];
int find1(int x){
	return fa1[x] == x?x:fa1[x] = find1(fa1[x]);
} 
int find2(int x){
	return fa2[x] == x?x:fa2[x] = find2(fa2[x]);
}
void merge1(int x,int y){
	int fx = find1(x),fy = find1(y);
	if(fx != fy) fa1[fx] = fy;
} 
void merge2(int x,int y){
	int fx = find2(x),fy = find2(y);
	if(fx!=fy) fa2[fx] = fy;
}
int main(){
	int n,m;scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i++) fa1[i] = i,fa2[i] = i;
	int cnt = 0;
	for(int i = 0;i < m;i++){
		int op,u,v;scanf("%d%d%d",&op,&u,&v);
		if(op == 1){
			if(find2(u) != find2(v)) cnt--;
			else cnt++;
			merge1(u,v);
		}else{
			if(find1(u) != find1(v)) cnt--;
			else cnt++;
			merge2(u,v);
		}
		if(!cnt) puts("A");
		else puts("B");
	}
	return 0;
}

你可能感兴趣的:(2020洛谷春季多校第二场E题--判断两图是否连通同构)