2019ICPC上海E Cave Escape(最大生成树)
这道题刚开始想到贪心去了,首先所有点都要取到,其次觉得一个点肯定是要跟最大的旁边点相连
但是这里有个问题,就是总是有一个点是原点,也就是这样直接贪心会存在环的情况,这种情况是不允许的,这意味着存在一个点即是出发点也是被遍历点
那么既要消除环的情况,又要连接所有的点,并且要求权值最大,基本上可以想到树
这题其实就是最大生成树问题,我们进一步可以发现,其实每种合法方案就是一颗树,一个点只能被一个点遍历过来,但是他可以对很多点产生贡献
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e6+10; int w[N]; struct node{ int a,b,w; bool operator <(const node &t) const{ return w<t.w; } }s[N]; int n,m,sr,sc,tr,tc; int x[N],A,B,C,P; int a[1010][1010]; int dx[]={0,1}; int dy[]={1,0}; int id[1010][1010]; int tot; int p[N]; map<int,int> m1; int find(int x){ if(p[x]!=x){ p[x]=find(p[x]); } return p[x]; } ll kruscal(){ sort(s+1,s+1+tot); int cnt=0; ll res=0; for(int i=1;i<=tot;i++){ int a=s[i].a,b=s[i].b,c=s[i].w; int pa=find(a); int pb=find(b); if(pa!=pb){ res+=c; p[pa]=pb; cnt++; if(cnt==n*m-1) break; } } return res; } int main(){ ios::sync_with_stdio(false); int t; cin>>t; int cas=0; while(t--){ tot=0; cin>>n>>m>>sr>>sc>>tr>>tc; cin>>x[1]>>x[2]>>A>>B>>C>>P; m1.clear(); int i,j; for(i=0;i<=n*m;i++) p[i]=i; for(i=3;i<=n*m;i++) x[i]=(A*x[i-1]+B*x[i-2]+C)%P; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ a[i][j]=x[(i-1)*m+j]; } } int idx=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++) id[i][j]=++idx; } int times=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ for(int k=0;k<2;k++){ int tmpx=i+dx[k]; int tmpy=j+dy[k]; if(tmpx>=1&&tmpx<=n&&tmpy>=1&&tmpy<=m){ int dd=id[tmpx][tmpy]; int dd1=id[i][j]; s[++tot]={dd,dd1,-a[i][j]*a[tmpx][tmpy]}; } } } } cout<<"Case #"<<++cas<<": "<<-kruscal()<<endl; } return 0; }
没有人不辛苦,只有人不喊疼