codeforces 884E Binary Matrix 并查集,滚动数组

来源:互联网 发布:ios开源app源码 编辑:程序博客网 时间:2024/04/30 03:20

E. Binary Matrix
time limit per test
3 seconds
memory limit per test
16 megabytes
input
standard input
output
standard output

You are given a matrix of size n × m. Each element of the matrix is either 1 or 0. You have to determine the number of connected components consisting of 1's. Two cells belong to the same component if they have a common border, and both elements in these cells are 1's.

Note that the memory limit is unusual!

Input

The first line contains two numbers n and m (1 ≤ n ≤ 2124 ≤ m ≤ 214) — the number of rows and columns, respectively. It is guaranteed that m is divisible by 4.

Then the representation of matrix follows. Each of n next lines contains  one-digit hexadecimal numbers (that is, these numbers can be represented either as digits from 0 to 9 or as uppercase Latin letters from A to F). Binary representation of each of these numbers denotes next 4 elements of the matrix in the corresponding row. For example, if the number B is given, then the corresponding elements are 1011, and if the number is 5, then the corresponding elements are 0101.

Elements are not separated by whitespaces.

Output

Print the number of connected components consisting of 1's.

题意:

超大矩阵超小内存求联通块数量。

题解:

按行扫描,保留上一行的状态以及上一行的并查集。

扫描到第i行时候,把第i行值为1且相邻的元素加入到并查集中去。

然后根据上一行的并查集,把第i行与上一行都为1且上下相邻的元素以上一行的元素的father点为标志,做一个等价类(等价类中包含的元素全都是第i行的)。

等价类中的元素意义是他们都可以通过i-1行进行互联,然后把他们加入到并查集里面去。

然后新的一行的并查集就建立完成了。

把新的并查集和旧的并查集交换,这样一直做下去。

代码:

#include <bits/stdc++.h>using namespace std;typedef pair<int,int> P;const int maxn = (1<<14)+10;int n,m;long long ans = 0;bool *line0,*line1;int mark[maxn];int *parents[2];int group[maxn];P stk[maxn];int top;inline int find(int *parent,int x){return parent[x] = x == parent[x]?x:find(parent,parent[x]);}inline void join(int *parent,int x,int y){int p1 = find(parent,x),p2 = find(parent,y);if(p1 == p2) return;parent[p1] = p2;}void initp(int *parent){for(int i = 0;i < maxn;++i) parent[i] = i;}int main(){ios_base::sync_with_stdio(0);cin.tie(0);string s;parents[0] = new int[maxn];parents[1] = new int[maxn];line1 = new bool[maxn];line0 = new bool[maxn];memset(line0,0,maxn*sizeof(bool));memset(line1,0,maxn*sizeof(bool));initp(parents[0]); cin>>n>>m;//n = 4096,m = 16384;for(int i = 1;i <= n+1;++i){memset(line0,0,maxn*sizeof(bool));memset(group,-1,sizeof(group));memset(mark,0,sizeof(mark));top = 0;if(i <= n){cin>>s;for(int j = m/4-1;j >= 0;j--){char c;c = s[m/4-1-j];//c = 'F';int num = c<='9'?c-'0':c-'A'+10;line0[4*j+0] = num&1;line0[4*j+1] = (num>>1)&1;line0[4*j+2] = (num>>2)&1;line0[4*j+3] = (num>>3)&1;}}for(int j = 0;j < m;++j){if(line1[j] && line0[j]) mark[find(parents[0],j)] = 1;}for(int j = 0;j < m;++j){if(line1[j] && !mark[find(parents[0],j)]){ans++;mark[find(parents[0],j)] = 1;}}initp(parents[1]);for(int j = 0;j < m;++j) if(line0[j] && line1[j]){int gp = find(parents[0],j);if(group[gp] == -1) group[gp] = j;else join(parents[1],group[gp],j),group[gp] = j;}for(int j = 0;j < m-1;j++){if(line0[j] && line0[j+1]) join(parents[1],j,j+1);}swap(line1,line0);swap(parents[0],parents[1]);}cout << ans << endl;return 0;} 




阅读全文
0 0
原创粉丝点击