1. 程式人生 > >Codeforces 985B 題解

Codeforces 985B 題解

n-1 lib cst 矩陣 初始 def ID ctype tchar

題意

有$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 題解