Codeforces 985B 题解

Posted rill7747

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 985B 题解相关的知识,希望对你有一定的参考价值。

题意

有$n$个开关和$m$盏灯,给定一个矩阵$a(a_{i,j}\in [0,1])$,若$a_{i,j}=1$则说明开关$i$与第$j$盏灯连接.初始时所有灯都是关闭的.按下某开关后,所有与这个开关连接的灯将会打开,已经打开的不会关闭.

现在你需要去掉一个开关,使得按下剩余$n-1$个开关后,所有灯都可以打开.若存在方案,则输出YES,否则输出NO.

题解

直观的想法为,枚举去掉的开关$i$,然后枚举每个与开关$i$相连的灯$j$,若存在一个$j$只能靠开关$i$打开(即矩阵第$j$列只有第$i$行为$1$),那么说明$i$不能去掉.

但是这是$\mathcal O(n^3)$的.

优化很简单,我们可以发现我们枚举了很多次某一列.直接记录$cnt_j$表示第$j$列中$1$的个数,也即第$j$盏灯连接这的开关数.

在判断时,直接判断$cnt_j$是否等于$1$即可.

时间复杂度$\mathcal O(n^2)$

代码

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cctype>
using namespace std;
const int N = 2005;
int n, m, cnt[N];
char a[N][N];
int main(){
    scanf("%d%d", &n, &m);
    for (register int i = 1; i <= n; ++i)
        for (register int j = 1; j <= m; ++j)
            while (!isdigit(a[i][j] = getchar()));
    for (register int i = 1; i <= n; ++i)
        for (register int j = 1; j <= m; ++j)
            cnt[j] += a[i][j] ^ ‘0‘; // 统计cnt
    for (register int i = 1; i <= n; ++i){
        register bool bo = true;
        for (register int j = 1; j <= m; ++j)
            if (a[i][j] == ‘1‘ && cnt[j] == 1) bo = false; // 直接判断即可
        if (bo) return printf("YES"), 0;
    }
    return printf("NO"), 0;
}

以上是关于Codeforces 985B 题解的主要内容,如果未能解决你的问题,请参考以下文章

codeforces比赛后怎么看题解和答案

Codeforces 1329 题解

Codeforces Round #805 (Div. 3) 题解

[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段

Codeforces Round #267 (Div. 2) C. George and Job

codeforces比赛后怎么看题解和答案