题目链接:http://codeforces.com/gym/102012/problem/A
题目给出的算法是通过异或和位移 , 每次生成不同的32位, 周期为2的32次方减1。题目的总边数太少,跑不出重边,所以有最小生成树的话就只有一个
#include<iostream> #include<algorithm> using namespace std; unsigned long long k1,k2; #define inf 0x3f3f3f3f #define mod 1000000007 int tot; unsigned long long xo() { unsigned long long k3=k1,k4=k2; k1=k4; k3^=k3<<23; k2=k3^k4^(k3>>17)^(k4>>26); return k2+k4; } struct edge{ int u,v; unsigned long long w; bool operator <(const edge &a)const{ return w<a.w; } }e[100010]; int n,m,fa[100010],cnt; unsigned long long ans; void add(int u,int v,unsigned long long w) { e[++cnt].u=u; e[cnt].v=v; e[cnt].w=w; } void gen() { int u,v; unsigned long long w; scanf("%d%d%llu%llu",&n,&m,&k1,&k2); cnt=0; for(int i=1;i<=m;i++) { u=xo()%n+1; v=xo()%n+1; w=xo(); add(u,v,w); } } int _find(int u) { if(fa[u]==u)return u; return fa[u]=_find(fa[u]);//路径压缩 } unsigned long long solve() { tot=1; sort(e+1,e+1+cnt); int u,v,x,y; unsigned long long w; ans=0; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=cnt;i++) { u=e[i].u;v=e[i].v;w=e[i].w; x=_find(u);y=_find(v); if(x!=y) { ans=(ans+w)%mod; tot++; fa[y]=x; if(tot==n)return ans; } } return 0; } int main() { int t; scanf("%d",&t); while(t--) { gen(); ans=inf; printf("%llu\n",solve()); } return 0; }
原文地址:https://www.cnblogs.com/chen99/p/11707579.html
时间: 2024-11-02 08:13:38