F-并查集(详解)

题目描述:维护一个 n 点的无向图,加入一条连接 u 和 v 的无向边,查询 u 和 v 的连通性。

解题思路:这是一个并查集的题,题目本来不难,不过有一些需要注意的地方,mod 998244353,表示对mod取余,即对998244353取余,求sum的时候需要边求边取,并的时候,应该统一以小的数字为根节点。

错误分析:注意输出。

题目

这是一道模板题。

维护一个 nn 点的无向图,支持:

  • 加入一条连接 uu 和 vv 的无向边
  • 查询 uu 和 vv 的连通性

由于本题数据较大,因此输出的时候采用特殊的输出方式:用 00 或 11 代表每个询问的答案,将每个询问的答案依次从左到右排列,把得到的串视为一个二进制数,输出这个二进制数 mod 998244353mod 998244353 的值。

请务必使用快读。

输入格式

第一行包含两个整数 n,mn,m,表示点的个数和操作的数目。

接下来 mm 行每行包括三个整数 op,u,vop,u,v

  • 如果 op=0op=0,则表示加入一条连接 uu 和 vv 的无向边;
  • 如果 op=1op=1,则表示查询 uu 和 vv 的连通性。

输出格式

一行包括一个整数表示答案。

样例

Input

Output

3 6

1 1 0

0 0 1

1 0 1

1 1 2

0 2 1

1 2 1

5

答案串为 01010101

数据范围与提示

n≤4000000,m≤8000000n≤4000000,m≤8000000

By zyz

AC代码 

#include<bits/stdc++.h>
using namespace std;
int f[4000010];
int n,m,op,a,b;
long long int ans=0;
const long long mod=998244353;
int getf(int v)
{
	if(f[v]==v)
		return v;
	else
	{
		f[v]=getf(f[v]);
		return f[v];
	}
}
void merge(int u,int v)
{
	int t1,t2,t;
	if(u>v)
	{
		t=u;
		u=v;
		v=t;
	}
	t1=getf(u);
	t2=getf(v);
	if(t1!=t2)
		f[t2]=t1;
}
int main()
{
	int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
		f[i]=i;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&op,&a,&b);
		if(op==0)
			merge(a,b);
		else
		{
			if(getf(a)==getf(b))
			{
				ans*=2;
				ans++;
				ans%=mod;
			}
			else
			{
				ans*=2;
				ans%=mod;	
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
 

努力努力再努力

猜你喜欢

转载自blog.csdn.net/zz_xun/article/details/119995155