2018徐州区域赛A. Rikka with Minimum Spanning Trees-最小生成树

题意:算出最小生成树的总边权和乘上不同最小生成树的个

题目给的生成随机数通过异或和位移 , 每次生成不同的32位, 周期为2的32次方减1。

重边的概率很小
也就是最小生成树如果有的话只有一个。
跑一遍Kruskal即可

/*************************************************************************
	> File Name: xuzhouA.cpp
	> Author: Hcacai
	> Created Time: 2019年10月27日 星期日 12时45分51秒
 ************************************************************************/
#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
const int N=2e5+100;
typedef unsigned long long ll;
unsigned long long k1, k2;
int tot;             //边的数目
struct edge{
   ll  u, v, w;
}e[N];  //边
int f[N];   //并查集
bool cmp( edge e1,  edge e2 )
{
	return e1.w<e2.w;  
}
void add(ll u, ll v, ll w)
{
	e[tot].u=u;
	e[tot].v=v;	
	e[tot++].w=w;
}
unsigned long long xorShift128Plus() {
	unsigned long long k3 = k1, k4 = k2;
	k1 = k4;
	k3 ^= k3 << 23;
	k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
	return k2 + k4;
}

int n,m;
void gen(){
scanf("%d%d%llu%llu", &n, &m, &k1, &k2);
for(int i = 1; i <= m; ++i) {
ll u = xorShift128Plus() % n + 1;
ll v = xorShift128Plus() % n + 1;
ll w = xorShift128Plus();
add(u,v,w);
add(v,u,w);
}
}
ll Find(ll x)  //查找跟节点
{
	if(f[x]==-1) return x; 
	return f[x]=Find(f[x]);
}
ll kruskal()
{

	sort(e,e+tot, cmp);
	memset(f,-1,sizeof(f));
	ll ans=0, sum=0;
	for(int i=0; i<tot; i++)
	{
	    ll u=e[i].u;
		ll v=e[i].v;
		ll w=e[i].w;
		ll t1=Find(u); 
		ll t2=Find(v);
		if(t1!=t2)
		{
			ans=(ans+w)%mod;
			f[t1]=t2;
			sum++;
		}
		if(sum == n-1) break;  //边的数目
	}
	if(sum<n-1) return 0;
	return ans%mod;
}
int main()
{
	int T;	
	scanf("%d", &T);
	while(T--)
	{
		tot=0;
		gen();
		ll ans=kruskal();
		printf("%lld\n", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值