牛客多校2020第三场

G题——(并查集+链表)

这题卡常的厉害,自己用set,想着暴力删边来维护关系,T到死,无论如何优化常数。看了一下官方题解,用链表,删边以及添加相邻-相邻边,才知道链表是O(1)操作,以前觉得没大用,原来链表得优势在这里。

附上题解做法
重要观察:在所有操作过程中,对于每个点,至多只会有一次把相邻的点和
自己变为同一种颜色的操作,经过该次操作后,就永远和相邻的点同色了。
• 参考做法:

  1. 对于每个颜色都维护一个点的链表,储存该颜色中尚未把所有相邻
    点变为自己颜色的点。
  2. 用并查集纪录每个点属于哪个颜色。
  3. 每次操作就会把颜色 oi 的链表中所有相邻的点所属的颜色都变为 oi ,
    就直接把对应的链表合并以及在并查集上做对应的操作。
    题目链接
//#pragma GCC optimize(2)
//#pragma GCC target ("sse4")
#include
//typedef long long ll;
#define ull       unsigned long long
//#define int       long long
#define F           first
#define S           second
#define endl        "\n"//<
#define eps         1e-6
#define base        131
#define lowbit(x)   (x&(-x))
#define PI          acos(-1.0)
#define inf         0x3f3f3f3f
#define MAXN        0x7fffffff
#define INF         0x3f3f3f3f3f3f3f3f
#define ferma(a,b)  pow(a,b-2)
#define mod(x)      (x%mod+mod)%mod
#define pb          push_back
#define decimal(x)  cout << fixed << setprecision(x);
#define all(x)      x.begin(),x.end()
#define rall(x)      x.rbegin(),x.rend()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS         ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
template<typename T> inline T fetch(){T ret;cin >> ret;return ret;}
template<typename T> inline vector<T> fetch_vec(int sz){vector<T> ret(sz);for(auto& it: ret)cin >> it;return ret;}
template<typename T> inline void makeUnique(vector<T>& v){sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());}
void file()
{
#ifdef ONLINE_JUDGE
#else
    freopen("D:/LSNU/codeforces/duipai/data.txt","r",stdin);
    //  freopen("D:/LSNU/codeforces/duipai/WA.txt","w",stdout);
#endif
}
const int N=8e5+5;
int fat[N],que[N];
list<int>G[N];
int find(int x)
{
    return fat[x]==x?x:fat[x]=find(fat[x]);
}
signed main()
{
    //IOS;
    file();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            fat[i]=i,G[i].clear();
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int x;
            scanf("%d",&x);
            que[0]=0;
            while(!G[x].empty())
            {
                que[++que[0]]=G[x].front();
                G[x].pop_front();
            }
            for(int i=1;i<=que[0];i++)
            {
                int v=que[i];
                int tv=find(v);
                if(tv==x)
                    continue;
                fat[tv]=x;
                G[x].splice(G[x].begin(),G[tv]);
            }
        }
        for(int i=0;i<n;i++)
            printf("%d ",find(i));
        printf("\n");
    }



    return 0;
}

你可能感兴趣的:(比赛)