题目链接: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 ; }