题目描述:
这是一道模板题。
维护一个n点的无向图,支持:
- 加入一条连接u和v的无向边
- 查询u和v的连通性
由于本题数据较大,因此输出的时候采用特殊的输出方式:用0或1代表每个询问的答案,将每个询问的答案依次从左到右排列,把得到的串视为一个二进制数,输出这个二进制数mod998244353的值。
请务必使用快读。
输入格式:
第一行包含两个整数n,m,表示点的个数和操作的数目。
接下来m行每行包括三个整数op,u,v。
- 如果op=0,则表示加入一条连接u和v的无向边;
- 如果op=1,则表示查询u和v的连通性。
输出格式:
一行包括一个整数表示答案。
输入输出样例
输入 #1
3 6
1 1 0
0 0 1
1 0 1
1 1 2
0 2 1
1 2 1
输出 #1
5
数据范围与提示
n≤4000000,m≤8000000
思路:
并查集模板题
代码:
#include<bits/stdc++.h>
using namespace std;
#define mod 998244353;
const int f=1e7+5;
int fa[f]={};
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int find(int x){
if(fa[x]==x){
return x;
}
return fa[x]=find(fa[x]);
}
void unit(int x,int y){
fa[find(x)]=find(y);
}
int main(){
int n,m;
cin>>n>>m;
int op,u,v,i0=0,an[m]={},i1=0;
for(int i=0;i<=n;i++){
fa[i]=-1;
}
for(int i=0;i<m;i++){
op=read();
u=read();
v=read();
if(op==0){
if(i1==1){
fa[u]=u;
fa[v]=u;
}
else{
if(fa[v]==-1){
fa[v]=u;
if(fa[u]==-1){
fa[u]=u;
}
}
else if(fa[u]==-1){
fa[u]=v;
}
else{
unit(u,v);
}
}
}
if(op==1){
if(u==v){
an[i0]=1;
}
else if(fa[u]==-1||fa[v]==-1){
}
else if(find(fa[u])==find(fa[v])){
an[i0]=1;
}
i0++;
}
}
long long sum=0;
long long p=1,pi=i0-1;
for(int i=i0-1;i>=0;i--){
if(an[i]==1){
if(pi!=i){
long long c=pow(2,pi-i);
c%=mod;
p=p*c;
p%=mod;
pi=i;
}
sum+=p;
sum%=mod;
}
}
write(sum);
return 0;
}