题目链接
You are given a graph containing n vertices and m edges. Vertices are numbered from 0 to n-1. Initially, vertex i belongs to group i. We define a group A is connected to group B if and only if there exists at least an edge that connects the two vertices which belong to A and B respectively.
Now we will do q operations on this graph. The i-th operation is represented by an integer o i o_i oi.
In i-th operation, if there are no vertices belong to group o i o_i oi, nothing happens. Otherwise, for all vertices belong to a group which is connected to o i o_i oi, those vertices will belong to group o i o_i oi after this operation.
Now you are also given the q operations. Please answer each vertex belongs to which group after all operations.
The first line contains one integer t ( 1 ≤ t ≤ 1.6 × 1 0 5 ) t (1 \le t \le 1.6 \times 10^5) t(1≤t≤1.6×105) — the number of test cases.
The first line of each test contains two positive integers n and m ( 2 ≤ n ≤ 8 × 1 0 5 , 1 ≤ m ≤ 8 × 1 0 5 ) (2 \le n \le 8 \times 10^5 , 1 \le m \le 8 \times 10^5) (2≤n≤8×105,1≤m≤8×105) — the number of vertices and edges in the given graph.
The following are m lines. Each of them contains two integers x and y, indicating there is an edge between vertex x and vertex y ( 0 ≤ x < y < n 0 \le x < y < n 0≤x<y<n, there are no duplicate edges in the same test)
The following line contains one integer q ( 1 ≤ q ≤ 8 × 1 0 5 ) (1 \le q \le 8 \times 10^5) (1≤q≤8×105) – the number of operations in this test. Then there is one more line contains q integers o 1 , o 2 , … , o q ( 0 ≤ o i < n ) o_1, o_2, \ldots, o_q (0 \le o_i < n) o1,o2,…,oq(0≤oi<n).
The sum of n across the test cases doesn’t exceed 8 × 1 0 5 8 \times 10^5 8×105.
The sum of m across the test cases doesn’t exceed 8 × 1 0 5 8 \times 10^5 8×105.
And the sum of q across the test cases doesn’t exceed 8 × 1 0 5 8 \times 10^5 8×105.
For each test, output one line contains n integers — the i-th integer of them representing the group that the vertex i-1 belongs to.
5
4 3
0 1
1 2
2 3
4
0 1 3 0
4 3
0 1
1 2
2 3
2
0 2
4 3
0 1
1 2
2 3
2
0 3
4 1
1 3
1
2
5 5
0 1
0 2
1 2
1 3
3 4
3
4 4 0
0 0 0 0
2 2 2 2
0 0 3 3
0 1 2 3
0 0 0 0 0
这题很明显的并查集,但是比较难看出是并查集+链表,我用别的数据结构就 T 了,我也是第一次学到了链表的拼接函数,还是见得太少~
我们用链表存储某一个块 o i o_i oi 的所有结点,每次遍历表头,存入所有和表头相连的未被访问的点,同时将点所属的块与表头的块用 s p l i c e splice splice 函数拼接,每次遍历整个链表一遍,最后输出时找每个顶点的父亲结点即可,AC代码如下:
#include
using namespace std;
typedef long long ll;
const int N=8e5+5;
int t,n,m,u,v,q,k,father[N],vis[N];
vector<int>G[N];
list<int>L[N];
int Findfather(int x){
return father[x]==x?x:father[x]=Findfather(father[x]);
}
void Union(int x,int y){
x=Findfather(x),y=Findfather(y);
if(x!=y) father[y]=x,L[x].splice(L[x].end(),L[y]);
}
void init(){
for(int i=0;i<=n;i++)
father[i]=i,vis[i]=0,G[i].clear(),L[i].clear(),L[i].push_back(i);
}
void bfs(int u){
if(Findfather(u)!=u) return;
int len=L[u].size();
for(int i=0;i<len;i++){
auto j=L[u].front();
for(auto v:G[j]){
Union(u,v);
if(vis[v]) continue;
L[u].push_back(v);
vis[v]=1;
}
L[u].pop_front();
}
}
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
while(m--){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%d",&q);
while(q--){
scanf("%d",&k);
bfs(k);
}
for(int i=0;i<n;i++){
printf("%d ",Findfather(i));
}
printf("\n");
}
}