题面:
题意:
给了一张图,一开始每个点在自己的集合中,如果存在一条边,其两个端点在不同集合中,我们认为这两个集合相邻。
每次选取一个点,若该点在自己的集合中,将该集合所有相邻的集合中间的点并入该集合中
输出q此操作后每个点所在的集合。
化简题意:
给一个 n 个点的 Graph,第 i 个点一刚开始是第 I 种颜色,接着有 k 次操作,第 i 次操作有个参数 oi 代表颜色 oi 会侵略所有和自己相邻的颜色,于是所有和 oi 相邻的颜色全都变成 oi (若已没有颜色oi 已被侵略,则该次操作无效),求最终每个点的颜色。
题解:
我们用并查集维护每个点所属的集合。
用链表维护每个集合有可能往外扩展的点,合并时,遍历这些有可能往外扩展的点,看看哪一些可以扩展,同时维护链表。链表的splice可以O(1)合并两个链表。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#include<list>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
//#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const