CF659FPolycarp and Hay(并查集,bfs)
Posted myx12345
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF659FPolycarp and Hay(并查集,bfs)相关的知识,希望对你有一定的参考价值。
题意:
构造一个矩阵,使得:
矩阵所有格子中数字都小于等于原矩阵,并且至少有一个元素和原矩阵相等,
构造的矩阵除了0以外的数字必须联通并且相等,矩阵中元素之和为K。
n,m<=1e3,1<=K<=1e18
思路:
From https://blog.csdn.net/morejarphone/article/details/51037918
对每个格子的数字进行排序,那么一个格子的数字最多能够填的格子数就是他上下左右格子能够填的格子
数的和,这个可以用并查集来维护
然后枚举每个格子,如果这个格子的数字能够整除k并且这个格子能够填的个数足够,就可以从这个格子出发
bfs一遍找到需要的格子
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second s 19 #define MP make_pair 20 #define N 1100 21 #define M 1100000 22 #define MOD 1000000007 23 #define eps 1e-8 24 #define pi acos(-1) 25 #define oo 2e9+1 26 27 int dx[4]={1,-1,0,0}, 28 dy[4]={0,0,-1,1}; 29 30 struct node 31 { 32 int x,y; 33 ll z; 34 }b[M],q[M]; 35 36 ll a[N][N],K; 37 int vis[N][N],num[N][N],f[M],size[M],n,m; 38 39 40 int read() 41 { 42 int v=0,f=1; 43 char c=getchar(); 44 while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();} 45 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 46 return v*f; 47 } 48 49 50 bool cmp(node a,node b) 51 { 52 return a.z>b.z; 53 } 54 55 int find(int k) 56 { 57 if(f[k]!=k) f[k]=find(f[k]); 58 return f[k]; 59 } 60 61 62 void bfs(int x,int y,ll cnt) 63 { 64 int t=0; 65 int w=1; 66 q[1].x=x; q[1].y=y; 67 memset(vis,0,sizeof(vis)); 68 vis[x][y]=1; 69 cnt--; 70 while(t<=w&&cnt) 71 { 72 t++; 73 int nowx=q[t].x; 74 int nowy=q[t].y; 75 vis[nowx][nowy]=1; 76 for(int i=0;i<4;i++) 77 { 78 int tx=nowx+dx[i]; 79 int ty=nowy+dy[i]; 80 if(!tx||tx>n||!ty||ty>m||vis[tx][ty]) continue; 81 if(a[tx][ty]>=a[x][y]) 82 { 83 vis[tx][ty]=1; 84 q[++w].x=tx; 85 q[w].y=ty; 86 cnt--; 87 if(cnt<=0) break; 88 } 89 } 90 } 91 for(int i=1;i<=n;i++) 92 { 93 for(int j=1;j<=m;j++) 94 { 95 if(vis[i][j]) printf("%lld",a[x][y]); 96 else printf("0"); 97 if(j<m) printf(" "); 98 } 99 printf(" "); 100 } 101 } 102 103 104 int main() 105 { 106 //freopen("cf659f.in","r",stdin); 107 //freopen("cf659f.out","w",stdout); 108 scanf("%d%d%lld",&n,&m,&K); 109 for(int i=1;i<=n;i++) 110 for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]); 111 int tot=0; 112 for(int i=1;i<=n;i++) 113 for(int j=1;j<=m;j++) 114 { 115 num[i][j]=(i-1)*m+j; 116 size[num[i][j]]=1; 117 f[num[i][j]]=num[i][j]; 118 b[++tot].x=i; 119 b[tot].y=j; 120 b[tot].z=a[i][j]; 121 } 122 sort(b+1,b+tot+1,cmp); 123 124 memset(vis,0,sizeof(vis)); 125 for(int i=1;i<=tot;i++) 126 { 127 vis[b[i].x][b[i].y]=1; 128 for(int j=0;j<4;j++) 129 { 130 int x=b[i].x+dx[j]; 131 int y=b[i].y+dy[j]; 132 if(x&&x<=n&&y&&y<=m&&vis[x][y]) 133 { 134 int p=find(num[b[i].x][b[i].y]); 135 int q=find(num[x][y]); 136 if(p!=q) 137 { 138 f[q]=p; 139 size[p]+=size[q]; 140 } 141 } 142 } 143 } 144 145 // for(int i=1;i<=n;i++) 146 // for(int j=1;j<=m;j++) printf("%d ",size[num[i][j]]); 147 148 int ans=0; 149 for(int i=1;i<=n;i++) 150 { 151 for(int j=1;j<=m;j++) 152 if(K%a[i][j]==0&&size[num[i][j]]>=K/a[i][j]) 153 { 154 printf("YES "); 155 bfs(i,j,K/a[i][j]); 156 ans=1; break; 157 } 158 if(ans) break; 159 } 160 if(!ans) printf("NO"); 161 162 } 163 164 165 166 167 168
以上是关于CF659FPolycarp and Hay(并查集,bfs)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #346 (Div. 2) (659A,659B,659C,659D(几何叉乘),659E(并查集))
CF #738(div2)D2. Mocha and Diana (Hard Version)(贪心,并查集)