题目链接:https://ac.nowcoder.com/acm/contest/4370/E
比板子稍微高级一点的题,难点在于读懂题意,和发现边的长度小于1e4使用桶排序的方法对边进行排序。
对结构体使用桶排序的方法
记录边数,前缀和得到该边长下为第几条边。再用另一个数组将其取出。
for(int i=1;i<=cnt;i++)
{
tonsort[e[i].dis]++;
}
for(int i=tonsortnum;i>=0;i--)
{
tonsort[i]+=tonsort[i+1];
}
for(int i=1;i<=cnt;i++)
{
ee[tonsort[e[i].dis]--]=e[i];
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int x[1000005],f[1005][1005],n,m,sr,sc,tr,tc,xx1,xx2,a,b,c,p,t;
int xxx[]={0,1},yyy[]={1,0};
int val[2000005],bcj[1000005],tt;//由于边数是2nm,所以边的数量是2000005;
const int tonsortnum=10005;
struct edge
{
int from,to,dis,pos;
}e[2000005];//e范围,只想右下搜边的数为n*m
edge ee[2000005];
bool cmp(edge a,edge b)
{
return a.dis>b.dis;
}
int find(int x)
{
if(bcj[x]==x)return x;
return bcj[x]=find(bcj[x]);
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
for(int tt=1;tt<=t;tt++)
{
ll cnt=0,ecnt=0;
cin>>n>>m>>sr>>sc>>tr>>tc;
cin>>xx1>>xx2>>a>>b>>c>>p;
x[1]=xx1;x[2]=xx2;
for(int i=3;i<=n*m;i++) //n*m,题目数据范围弄错,还导致x值有问题
{
x[i]=(a*x[i-1]+b*x[i-2]+c)%p;//加c呢,加c呢..
}
/*for(int i=3;i<=n*m;i++)
{
cout<<x[i]<<' ';
}*/
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
f[i][j]=x[(i-1)*m+j];//i-1有括号,有括号。。。
}
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<f[i][j]<<' ';
}
cout<<endl;
}*/
/* for(int i=1;i<=n;i++)
{
cout<<val[i]<<' ';
}*/
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=0;k<2;k++)//只向右下搜
{//代码过于繁琐,重构
int xx=i+xxx[k],yy=j+yyy[k];
if(xx>=1&&yy>=1&&xx<=n&&yy<=m)//*
{
e[++cnt].dis=f[i][j]*f[xx][yy];
e[cnt].from=(i-1)*m+j;
e[cnt].to=(xx-1)*m+yy;
e[cnt].pos=cnt;
}
}
}
}
/*for(int i=1;i<=cnt;i++)
cout<<e[i].dis<<' '<<e[i].from<<' '<<e[i].to<<' '<<endl;*/
int tonsort[tonsortnum]={0},toncnt=0,tontmp[tonsortnum]={0};
/*for(int i=1;i<=cnt;i++)
{
cout<<e[i].dis<<' ';
}*/
//cout<<endl;
for(int i=1;i<=cnt;i++)
{
tonsort[e[i].dis]++;
}
for(int i=tonsortnum;i>=0;i--)
{
tonsort[i]+=tonsort[i+1];
}
for(int i=1;i<=cnt;i++)
{
ee[tonsort[e[i].dis]--]=e[i];
}
/*for(int i=1;i<=cnt;i++)
{
cout<<ee[i].dis<<' ';
}*/
//sort(e+1,e+cnt+1,cmp);//由于使用的是++cnt,故cnt最终的数量等于边的数量,故为e+cnt+1;
int cntm=0;
for(int i=1;i<=n*m;i++)bcj[i]=i;
for(int i=1;i<=cnt;i++)//最终边的数量并不是n*m条,而是2*n*m条,也就是cnt条
{
int ff=find(ee[i].from),ft=find(ee[i].to);
if(ff!=ft)
{
bcj[ff]=ft;
ecnt+=ee[i].dis*1LL;
cntm++;
if(cntm==n*m-1)break;
}
}
cout<<"Case #"<<tt<<": "<<ecnt<<endl;
}
return 0;
}