【CF659F】Polycarp 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("\n");
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\n",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\n");
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         

原文地址:https://www.cnblogs.com/myx12345/p/9718159.html

时间: 2024-10-21 22:14:10

【CF659F】Polycarp and Hay(并查集,bfs)的相关文章

ZOJ - 4109 - Welcome Party (并查集 + BFS + 优先队列)

题目地址 题目大意:n个人,m种关系 (a和b是朋友),可以看作 n个点,m条边, 用图论的知识解题 问在使最少人不开心的情况下,输出进房间字典序排序最小的顺序.(如果在小A进房间之前房间内没有他的朋友,他就不开心) 使用并查集分块,每个并查集的根节点和独立点(无朋友)的总个数就是输出的不开心的人数.     使用BFS和优先队列遍历存入的图,保证字典序最小.将路径存入答案数组. 代码: #include <bits/stdc++.h> using namespace std; const i

ZOJ 3811 / 2014 牡丹江赛区网络赛 C. Untrusted Patrol bfs/dfs/并查集

Untrusted Patrol Time Limit: 3 Seconds                                     Memory Limit: 65536 KB Edward is a rich man. He owns a large factory for health drink production. As a matter of course, there is a large warehouse in the factory. To ensure t

2017省夏令营Day8 【bfs,并查集】

题解:出题人丧心病狂~ 对于这道题,我们对每一个内应节点bfs,并用并查集维护,如果s和t联通,输出答案并break. PS几个小细节:①对于每个内应dis=0,为了保证不会对答案产生影响,我们在每2个节点中插入一个新的节点即可: ②因为加入新节点,数组要开大些,否则会炸. 代码如下: 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define Max 2020304 5 using nam

洛谷P1547 Out of Hay 最小生成树 并查集

洛谷P1547 Out of Hay 最小生成树 并查集 路径压缩 #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <iomanip> using namespace std ;

ZOJ 3811 Untrusted Patrol bfs+并查集

题目链接:点击打开链接 题意: 给定n个点m条边的无向图,k个触发器. 下面k个数表示触发器安装在哪几个点. 下面m行给出边 最后有l个信号, 给出信号发出的触发器的顺序. 每个触发器只会发出一次信号,且一个点只有一个触发器. 有一个人在遍历图. 每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样. 思路: 先把无触发器的点放到图里. 然后根据触发器的信号顺序把点依次加入图中,加入时只添加(与无触发器点相连的边) 然后判断这个点能

第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 63  解决: 28 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以

畅通工程(自己写的BFS,但后面想了下并查集更好更快)

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1到N编号. 注意:两个城市

分别利用并查集,DFS和BFS方法求联通块的数量

联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m行(输入数据到文件截止): 输出:第一行要求输出联通块的个数,并在第二行分别输出每个联通块中点的数量,每个数之间以一个空格隔开. 样例 15 31 42 53 5输出:2 2 3样列2 9 81 22 33 43 74 54 67 87 9输出: 19 如果不明白的话可以画图试试,最多花半个小时,要是早这样不

UVA 11165 - Galactic Travel(BFS+twopointer+并查集)

UVA 11165 - Galactic Travel 题目链接 题意:给定一些不能走的边,要求出从s到t的最短路 思路:由于点数多,直接广搜会超时,所以加上优化,已经找过的点就不在重复找了,这点可以利用并查集进行优化,然后对于每个点的每个不能走的区间,可以先排序,然后利用twopointer的性质,每次可以从上次找到的位置往后找即可 代码: #include <cstdio> #include <cstring> #include <algorithm> #inclu