Codeforces 985B 題解
阿新 • • 發佈:2018-05-26
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 題解