题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest

A. Rikka with Minimum Spanning Trees

题意:

给出一个随机算法生成边的信息,然后求最小生成树的个数以及其权值的乘积。

 

题解:

这个随机算法有点神奇...基本不会有重复的边出现,所以其实只用求MST就行了。当然,其实通过样例也可以猜出来,样例生成了1W条边,但最后的answer就为最小生成树权值,所以可以直接根据这个来猜一发,注意一下判断是否连通就行了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+5;
const int MAXM = 3e5+5;
const int MOD = 1e9+7;
const double eps = 1e-7;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i = (a);i<=(b);i++)
struct Edge{
    int u,v;
    ull w;
    bool operator <(const Edge &ds)const{
        return w<ds.w;
    }
}e[MAXM];
int n,m,fa[MAXN];
int t,tot;
//double G[MAXN][MAXN];
ull k1,k2;
ull ans=0;
ull xorShift128Plus(){
    ull k3=k1,k4=k2;
    k1=k4;
    k3 ^= k3<<23;
    k2 = k3 ^ k4 ^ (k3 >>17) ^(k4 >>26);
    return k2 +k4;
}
void gen(){
    cin >>n >>m >>k1 >>k2;
    int u,v;
    ull w;
    tot = ans = 0;
    rep(i,1,m){
        u = xorShift128Plus()%n+1;
        v = xorShift128Plus()%n+1;
        w = xorShift128Plus();
        if(u == v) continue ;
        //cout <<u<<' ' <<v<<' ' <<w <<'\n';
        e[++tot] = {u,v,w};
    }
}
int find(int x){
    return x==fa[x]?x:fa[x] = find(fa[x]);
}
bool kruskal(){
    int ss=0;
    sort(e+1,e+1+tot);
    rep(i,1,n)fa[i] =i;
    rep(i,1,tot){
        int a = find(e[i].u),b =find(e[i].v);
        if(a!=b){
            fa[a] =b;
            ans = (ans +e[i].w%MOD)%MOD;
            ss++;
        }
    }
    return ss==n-1;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0) ;
    cin >>t;
    while(t--){
        gen();
        if(!kruskal()){
            cout << 0<<'\n';
        }else{
            cout << ans <<'\n';
        }
    }
    return 0 ;
}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2018-09-10
  • 2022-02-13
  • 2021-08-18
  • 2021-08-22
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-12-16
  • 2022-12-23
  • 2022-12-23
  • 2021-07-23
相关资源
相似解决方案