• 牛客练习赛68C 牛牛的无向图(并查集)


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

    题意:定义 d(u,v) 表示在无向图中点 u 能到达点 v 的所有路径中权值最小的路径的权值(一条路径的权值是这个路径包含的边的权值的最大值),q个询问 每次问有多少个d(u,v)<=L,求q个询问答案的异或值

    分析:对于每个询问给定的限制L,我们只要考虑小于L权值的边组成的图会造成多大贡献即可(因为要选权值最小,要是有大边加上u和v,也不会选它)。对于每一条小于等于L的边,若这条边作为权值,那么肯定是作为“已形成图”的俩连通分量的桥,贡献就为size[u]*size[v],用并查集维护即可。

       由于是考虑大小关系的,所以把边的权值和询问的L作为权值排序查询即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    #define pb push_back
    #define ull unsigned long long
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long ll;
    const ll INF=1e18;
    const int inf=0x3f3f3f3f;
    const int M=1e6+6;
    const int mod=199999;
    int u[M],v[M],w[M],L[M],f[M],sz[M];
    struct node{
        int u,v,w,op,id;
    }e[M];
    ll ans[M],now=0;
    unsigned int SA, SB, SC;
    int n, m, q, LIM;
    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;
    }
    
    void gen(){
        scanf("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
        for(int i = 1; i <= m; i++){
            u[i] = rng61() % n + 1;
            v[i] = rng61() % n + 1;
            w[i] = rng61() % LIM;
        }
        for(int i = 1; i <= q; i++){
            L[i] = rng61() % LIM;
        }
    }
    int Find(int x){
        return x==f[x]?x:f[x]=Find(f[x]);
    }
    void Merge(int x,int y){
        x=Find(x),y=Find(y);
        if(x==y)
            return ;
        now+=sz[x]*sz[y];
        f[y]=x;
        sz[x]+=sz[y];
    }
    int main(){
        gen();
        for(int i=1;i<=m;i++)
            e[i].u=u[i],e[i].v=v[i],e[i].w=w[i],e[i].op=1;
        for(int i=1;i<=q;i++)
            e[i+m].id=i,e[i+m].w=L[i],e[i+m].op=2;
        int tot=m+q;
        for(int i=1;i<=n;i++)
            f[i]=i,sz[i]=1;
        sort(e+1,e+1+tot,[&](node A,node B){
            if(A.w==B.w)
                return A.op<B.op;
            return A.w<B.w;
        });
        for(int i=1;i<=tot;i++){
            if(e[i].op==1)
                Merge(e[i].u,e[i].v);
            else
                ans[e[i].id]=now;
        }
        ll res=0;
        for(int i=1;i<=q;i++)
            res^=ans[i];
        printf("%lld",res);
        return 0;
    }
    View Code
  • 相关阅读:
    选择排序与冒泡排序
    判断是否为偶数
    mysql基础之mysql双主(主主)架构
    mysql基础之mysql主从架构半同步复制
    mysql基础之mysql主从架构
    mysql基础之数据库备份和恢复实操
    mysql基础之数据库备份和恢复的基础知识
    mysql基础之日志管理(查询日志、慢查询日志、错误日志、二进制日志、中继日志、事务日志)
    mysql基础之查询缓存、存储引擎
    mysql基础之数据库变量(参数)管理
  • 原文地址:https://www.cnblogs.com/starve/p/13580134.html
Copyright © 2020-2023  润新知