隐藏
「codevs1995」黑魔法师之门 - 并查集 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「codevs1995」黑魔法师之门 - 并查集

题目大意

经过了16个工作日的紧张忙碌,未来的人类终于收集到了足够的能源。然而在与Violet星球的战争中,由于Z副官的愚蠢,地球的领袖applepi被邪恶的黑魔法师Vani囚禁在了Violet星球。为了重启Nescafé这一宏伟的科技工程,人类派出了一支由XLk、Poet_shy和lydrainbowcat三人组成的精英队伍,穿越时空隧道,去往Violet星球拯救领袖applepi。
applepi被囚禁的地点只有一扇门,当地人称它为“黑魔法师之门”。这扇门上画着一张无向无权图,而打开这扇门的密码就是图中每个点的度数大于零且都是偶数的子图的个数对$1000000009$取模的值。此处子图$(V,E)$定义为:点集$V$和边集$E$都是原图的任意子集,其中$E$中的边的端点都在$V$中。
但是Vani认为这样的密码过于简单,因此门上的图是动态的。起初图中只有$N$个顶点而没有边。Vani建造的门控系统共操作$M$次,每次往图中添加一条边。你必须在每次操作后都填写正确的密码,才能够打开黑魔法师的牢狱,去拯救伟大的领袖applepi。


题目分析

考虑,每个点都是偶点的子图必定由环组成,若$x\leftrightarrow y$连接两个不同的集合,那么没有新环增加,否则说明有新环增加。

$($新图中的环$)=($原图中的环$)+($原图中的环$+$新环$)+($新环$)=2lastans+1$

用并查集维护连通性。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const LL mod=1000000009;
LL ans=0;
int n,m,father[200005];
int Get_Father(int x) {
if(father[x]==x)return x;
else return father[x]=Get_Father(father[x]);
}
int main() {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=n; i++)father[i]=i;
for(int i=1; i<=m; i++) {
int x=Get_Int(),y=Get_Int();
int fx=Get_Father(x),fy=Get_Father(y);
if(fx!=fy) {
father[fx]=fy;
printf("%lld\n",ans);
} else {
ans=(2*ans+1)%mod;
printf("%lld\n",ans);
}
}
return 0;
}
姥爷们赏瓶冰阔落吧~