题目
Description
applepi被囚禁的地点只有一扇门,当地人称它为“黑魔法师之门”。这扇门上画着一张无向无权图,而打开这扇门的密码就是图中【每个点的度数大于零且都是偶数】的子图的个数对1000000009
取模的值。此处子图 (V, E)
定义为:点集V
和边集E
都是原图的任意子集,其中E
中的边的端点都在V
中。但是Vani认为这样的密码过于简单,因此门上的图是动态的。起初图中只有N
个顶点而没有边。Vani建造的门控系统共操作M
次,每次往图中添加一条边。你必须在每次操作后都填写正确的密码,才能够打开黑魔法师的牢狱,去拯救伟大的领袖applepi。
Input
第一行包含两个整数N
和M
。
接下来M
行,每行两个整数A
和B
,代表门控系统添加了一条无向边 (A, B)
。
N≤200000
,M≤300000
Output
输出一共M
行,表示每次操作后的密码。
题解
一道海星的并查集
主要难度在理解题意上了
代码
#include <cstdio>
#include <vector>
using namespace std;
class UnionFind {
private:
int quantity;
vector<int> union_;
public:
UnionFind(const int maximum = 1) {
union_.assign(maximum + 10, 0);
quantity = maximum;
for (register int i(1); i <= maximum; ++i) {
union_[i] = i;
}
}
inline void Assign(const int &maximum) {
union_.clear();
union_.assign(maximum + 10, 0);
quantity = maximum;
for (register int i(1); i <= maximum; ++i) {
union_[i] = i;
}
}
inline int Find(const int &x) {
return union_[x] == x ? x : union_[x] = Find(union_[x]);
}
inline void Merge(const int &u1, const int &u2) {
const int tmp1(this->Find(u1)), tmp2(this->Find(u2));
union_[tmp2] = tmp1, union_[u2] = tmp1;
}
};
UnionFind unions;
const int kMod(1000000009);
int n, m, x, y, ans(1);
int main(int argc ,char **argv) {
scanf("%d %d", &n, &m);
unions.Assign(n);
while (m--) {
scanf("%d %d", &x, &y);
if (unions.Find(x) != unions.Find(y))unions.Merge(x, y);
else ans *= 2;
if (ans > kMod) ans -= kMod;
printf("%d\n", ans - 1);
}
return 0;
}
原文地址:https://www.cnblogs.com/forth/p/9532909.html
时间: 2024-10-17 15:37:38