标签:ll int kruskal 多校 fa 排序 include find 第三场
可以发现将整张图涂完需要n+m-1次,而每涂完一个点,这个点便可以影响到此点所在的一整列和一整行,我们考虑每填涂完一个点后将这些行和列放入一个连通块,则容易得出:当所有行和列连通时,填涂完毕。
行和列的总和一共有n+m,填涂需要n+m-1次,需要用到连通块,这三点结合起来容易让人想到Kruskal算法求最小生成树
需要注意的时,kruskal需要排序,而当极限数据时,点数总数n*m=25000000,此时快速排序是一定会超时的,考虑使用其他排序方法,观察数据范围发现p的大小不超过100000,于是考虑使用桶排序,则此时的时间复杂度可以接受
#include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<vector> using namespace std; #define ll long long int fa[2000020]; ll ans; int a,b,c,d,p; int n,m; struct U{ int x; int y; ll z; U(int x_,int y_,ll z_):x(x_),y(y_),z(z_){} }; vector<U>E[1000010]; int find(int x) { if(fa[x]==x)return x; else return fa[x]=find(fa[x]); } void unio(int x,int y) { fa[find(x)]=find(y); } int cnt=1; void work() { cnt=n+m-1; //int now=min(n*m,2000000); int now=n*m; for(int k=0;k<=p;k++) { for(int i=0;i<E[k].size();i++) { if(!cnt)break; if(find(E[k][i].x)==find(E[k][i].y+n))continue; unio(E[k][i].x,E[k][i].y+n); cnt--; ans+=E[k][i].z; } } cout<<ans; } int cmp(U a,U b) { return a.z<b.z; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n+m;i++)fa[i]=i; scanf("%d%d%d%d%d",&a,&b,&c,&d,&p); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { int t; int A; ans++; A=a; t=((ll)A*A*b+(ll)A*c+d)%p; a=t; E[t].push_back(U(i,j,t)); } } ans=0; work(); return 0; }
标签:ll,int,kruskal,多校,fa,排序,include,find,第三场 来源: https://www.cnblogs.com/lemonGJacky/p/15303874.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。