题: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; }