E. Binary Matrix 【并查集】2500

E. Binary Matrix

图片说明

图片说明

题意

给一个很大的矩阵,问联通块的个数是多少。其中因为矩阵非常大,用的16进制输入的。

解法

这题非常卡常,光是读入量就已经1.6e7了,所以这里我使用了getchar()来读入。
然后对于联通块的个数,就是总的1个数 - 并查集合并的次数

考虑一行一行处理并查集,同一行遍历相邻两个字符,进行合并,不同行,就当前行跟上一行进行合并,在同为1的时候。
对于并查集的fa[]数组,其值需要再下一次做并查集的时候进行改变。

上一行的fa[]数组,范围是,下一行是, 当处理完这两行的后,要把下一行作为下一次操作的上一行,要做以下2个操作:

  1. 将字符串进行拷贝到上一行
  2. 将fa[]数组映射到,这样就不含引起并查集冲突。

代码

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define debug_in  freopen("in.txt","r",stdin)
#define debug_out freopen("out.txt","w",stdout);
#define pb push_back
#define all(x) x.begin(),x.end()
#define fs first
#define sc second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pii;
const ll maxn = 1e5+100;
const ll maxM = 1e6+10;
const ll inf = 1e8;
const ll inf2 = 1e17;

template<class T>void read(T &x){
    T s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    x = s*w;
}
template<class H, class... T> void read(H& h, T&... t) {
    read(h);
    read(t...);
}

template<class T> void pt(T x){
    cout<<x<<" ";
}

template <typename T, typename... Args>
void pt(const T& t, const Args& ... data){
    cout<<t<<" ";
    pt(data...);
}


//--------------------------------------------

int N,M;
char line1[maxn];
char line2[maxn];
int fa[maxn*2];
int ind[maxn*2];
void work(char line[],int idx,char c){
    int v;
    if('0' <=c && c <='9') v = c - '0';
    else v = 10 + c-'A';
    int w[4],tail = 3;
    for(int i = 0;i<4;i++) w[i] = 0;
    while(v){
        w[tail--] = v%2;
        v/=2;
    }
    for(int i = 0;i<4;i++){
        line[idx+i] = '0'+w[i];
    }
}
int total = 0,bin = 0;
int find(int x){
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void solve(){
    for(int j = 1;j<=M;j++) fa[M+j] = M+j;
    for(int j = 2;j<=M;j++){
        if(line2[j-1] == '1' && line2[j] == '1'){
            int fx = find(M + j-1),fy = find(M + j);
            if(fx != fy){
                bin++;
                fa[fx] = fy;
            }
        }
    }
    for(int j = 1;j<=M;j++){
        if(line1[j] == '1' && line2[j] == '1'){
            int fx = find(j),fy = find(M+j);
            if(fx != fy){
                bin++;
                fa[fx] = fy;
            }
        }
    }
}
void init(){ //把下一行的信息,拷贝到上一行,并重新映射fa数组
    for(int i = 1;i<=2*M;i++) ind[i] = 0;
    for(int j = 1;j<=M;j++) fa[M+j] = find(M+j);
    for(int j = 1;j<=M;j++){
        if(ind[fa[M+j]] == 0){
            ind[fa[M+j]] = j;
        }
    }
    for(int j = 1;j<=M;j++){
        fa[j] = ind[fa[M+j]];
    }
    for(int j = 1;j<=M;j++) line1[j] = line2[j];
}
int main(){
    // debug_in;

    read(N,M);
    for(int j = 1;j<=M;j++) fa[j] = j;
    for(int i = 1;i<=N;i++){
        for(int j = 1;j<=M/4;j++){
            char c;c = getchar();
            while(!(('0'<=c &&c <='9') || ('A'<=c && c<='F'))) c = getchar();//加快读入
            work(line2,(j-1)*4 + 1,c); //填入到字符数组中
        }
        for(int j = 1;j<=M;j++) if(line2[j] == '1') total++;
        if(i == 1) { //第一行特殊处理
            for(int j = 1;j<=M;j++) fa[M + j] = M + j;
            for(int j = 2;j<=M;j++) {
                if(line2[j-1] == '1' && line2[j] == '1'){
                    int fx = find(M + j-1),fy = find(M + j);
                    if(fx != fy){
                        bin++;
                        fa[fx] = fy;
                    }
                }
            }
            init();
        }
        else {
            solve();
            init();
        }

    }
    printf("%d\n",total - bin);


    return 0;
}
全部评论

相关推荐

脾气小祖宗:这简历摸到都得狠狠地消毒液洗手😂
点赞 评论 收藏
分享
Hyh_111:像这种hr就不用管了,基本没啥实力,换一个吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 你的mentor是什么样的人? #
4503次浏览 33人参与
# 你觉得mentor喜欢什么样的实习生 #
10715次浏览 297人参与
# 未岚大陆求职进展汇总 #
38142次浏览 114人参与
# 帮我看看,领导说这话什么意思? #
6647次浏览 26人参与
# 26届秋招公司红黑榜 #
13171次浏览 44人参与
# 怎么给家人解释你的工作? #
1646次浏览 17人参与
# 智慧芽求职进展汇总 #
25917次浏览 110人参与
# 没有家庭托举的我是怎么找工作的 #
12676次浏览 160人参与
# 求职低谷期你是怎么度过的 #
5423次浏览 96人参与
# 实习必须要去大厂吗? #
146833次浏览 1542人参与
# 从哪些方向判断这个offer值不值得去? #
6777次浏览 95人参与
# 同bg的你秋招战况如何? #
158879次浏览 927人参与
# 度小满求职进展汇总 #
10221次浏览 53人参与
# 校招泡的最久的公司是哪家? #
4840次浏览 23人参与
# 面试紧张时你会有什么表现? #
1802次浏览 21人参与
# 你有哪些缓解焦虑的方法? #
37205次浏览 835人参与
# 你喜欢工作还是上学 #
77620次浏览 860人参与
# 入职第一天,你准备什么时候下班 #
85519次浏览 467人参与
# 秋招想进国企该如何准备 #
97750次浏览 487人参与
# 简历无回复,你会继续海投还是优化再投? #
103620次浏览 819人参与
# 机械人的工作环境真的很差吗 #
25086次浏览 119人参与
# 独居后,你的生活是更好了还是更差了? #
28154次浏览 263人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务