• 最小生成树集合合并


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

      

    寻找真正的热爱
  • 相关阅读:
    支付方法及注意事项
    网站负载均衡策略
    工作成长
    java内存机制
    关于前途的一些思考
    git记录
    关于博客
    如何为公司创造价值?
    遍历集合方法总结
    二叉树和红黑二叉树
  • 原文地址:https://www.cnblogs.com/lesning/p/13610990.html
Copyright © 2020-2023  润新知