Dreamoon-Operating on a graph(并查集+链表)

题意:

每次操作可以输入一个颜色,然后所有这个颜色的点使相邻的点都变成这个颜色,最后输出每个点是什么颜色。

题解:

对每个节点开一个链表,存储与这个节点相邻的节点。

然后对于每次操作,把节点周围的节点全都变成相同颜色的节点,然后清空这些节点对应的链表,把链表接到父节点下。

#include<bits/stdc++.h>
using namespace std;
const int maxn=8e5+100;
int t;
int n,m;
int father[maxn];
int findfather (int x) {
    int a=x;
    while (x!=father[x]) x=father[x];
    while (a!=father[a]) {
        int z=a;
        a=father[a];
        father[z]=x;
    }
    return x;
}
void Union (int x,int y) {
    int faX=findfather(x);
    int faY=findfather(y);
    father[faY]=faX;
}
int main () {
    scanf("%d",&t);
    while (t--) {
        scanf("%d%d",&n,&m);
        list<int> g[n];
        for (int i=0;i<n;i++) father[i]=i;
        for (int i=0;i<m;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x].push_back(y);
            g[y].push_back(x);
        }
        int q;
        scanf("%d",&q);
        for (int i=0;i<q;i++) {
            int x;
            scanf("%d",&x);
            if (father[x]!=x) continue;
            vector<int> wjm;
            for (auto it=g[x].begin();it!=g[x].end();it++) {
                int y=*it;
                wjm.push_back(y);
                //Union(x,y);
                //printf("%d ",y);
            }
            g[x].clear();
            for (int j=0;j<wjm.size();j++) {
                int y=findfather(wjm[j]);
                g[x].splice(g[x].end(),g[y]);
                father[y]=x;
            }
            //printf("
");
        }
         
        for (int i=0;i<n;i++) printf("%d ",findfather(i));
        printf("
");
    }
}
原文地址:https://www.cnblogs.com/zhanglichen/p/13373989.html