G Operating on a Graph(并查集+临边染色)

题:https://ac.nowcoder.com/acm/contest/5668/G

题意:给定n点m边图,q个询问,每个询问为x颜色,若此时图上有x颜色的部分,这该部分临边的部分会被染成x颜色(有可能是一个点,有可能是同种颜色的子图)

分析:因为一种颜色只能由一次覆盖临边的机会,所以每次操作只需要维护子图的“祖”颜色和该子图的临边部分即可。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
typedef long long ll;
const int mod=1e9+7;
const int M=8e5+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
vector<int>g[M],col[M],tmp;
int f[M];
int Find(int x){
    return x==f[x]?x:f[x]=Find(f[x]);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            f[i]=i,col[i].clear(),g[i].clear();
        for(int u,v,i=0;i<m;i++){
            scanf("%d%d",&u,&v);
            g[u].pb(v);
            g[v].pb(u);

        }
        int q;
        scanf("%d",&q);
        while(q--){
            int x;
            scanf("%d",&x);
            if(Find(x)!=x)
                continue;
            tmp.clear();
            tmp=g[x];
            g[x].clear();
            for(auto now:tmp){
                int u=Find(now);
                if(u!=x){
                    f[u]=x;
                    ///合并未染色的未染色
                    if(g[x].size()<g[u].size())
                        swap(g[x],g[u]);
                    for(auto v:g[u])
                        g[x].pb(v);
                }
            }
        }
        for(int i=0;i<n;i++)
            printf("%d ",Find(i));
        printf("
");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/13337264.html