最小生成树集合合并

https://ac.nowcoder.com/acm/contest/7079/C

由题可知是最小生成树,先把比L【i】小的连通块建立好,合并集合x,y可得-----》  par[y] = x,ans += siz[x]*siz[y],siz[x] += siz[y];

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
unsigned int SA, SB, SC; int n, m, q, LIM;
const int maxn = 5e5+11;
typedef long long ll;

unsigned int rng61(){
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}
struct Node{
	int x,y,w;
	bool operator <(const Node b){
		return w < b.w;
	}
}que[maxn];
int L[maxn];

void gen(){
    scanf("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
    for(int i = 1; i <= m; i++){
    	que[i].x = rng61() % n + 1;
        que[i].y = rng61() % n + 1;
        que[i].w = rng61() % LIM;
    }
    for(int i = 1; i <= q; i++){
        L[i] = rng61() % LIM;
    }
}
ll par[maxn],siz[maxn];
int find(int x){
	if(par[x] == -1) return x;
	return par[x] = find(par[x]); 
}

int main(){
	gen();
	for(int i=1;i<=n;i++){
		par[i] = -1;
		siz[i] = 1;
	}
	
	sort(que+1,que+1+m);
	
	sort(L+1,L+1+q);
	int j = 1;
	ll s = 0;
	ll ans = 0;
	for(int i=1;i<=q;i++){
		for(;j<=m && que[j].w<= L[i];j++){
			int x = find(que[j].x);
			int y = find(que[j].y);
	
			if(x != y) {
				par[x] = y;
				s += 1LL*siz[y]*siz[x];
				
				siz[y] += siz[x];
			}
		}
	
		ans ^= s;
	}
	cout<<ans<<endl;
	return 0;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/13610990.html