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