UOJ UER#5 A 萬聖節的南瓜燈

紅包是一個心靈手巧的男孩子。今天是萬聖節,紅包正在家裏製作南瓜燈。

這時候一羣熊孩子們敲開了紅包家的門,他們高呼着“不用給糖,只要搗蛋”的口號把紅包的南瓜燈弄壞了。這讓紅包很難過,於是他打算把這些被弄壞的南瓜燈做成其他的工藝品。

紅包把它的南瓜燈劃分成了 n×m 的網格,並用 (x,y) 表示第 x 行,第 y 列的格子。兩個格子是相鄰的當且僅當它們有一條公共邊,特殊地, (x,1)(x,m) 紅包也視爲是相鄰的,但是他不把 (1,x)(n,x) 當做是相鄰的。

對於一個有 K 個格子被弄壞的南瓜燈,如果它能被製作成工藝品,當且僅當對於任意兩個沒有被弄壞的格子,都存在且僅存在一條連接它們的簡單路徑。一條簡單路徑定義爲一個只包含沒有被弄壞的格子的序列A1An ,其中對於任意的 1i<n 都有 AiAi+1 是相鄰的,且每一個格子在序列中至多出現了一次。

現在紅包有 T 個南瓜燈,他想讓你幫他分別判斷每一個南瓜燈能不能被做成工藝品。

輸入格式

第一行一個正整數 T,表示南瓜燈數目。

對於每一個南瓜燈,第一行是三個整數 n,m,K,表示南瓜燈的大小和被弄壞的格子數。

接下來 K 行每行包含兩個整數 x,y1xn,1ym),表示第x 行第 y 列的格子被弄壞了。

數據保證 n,m30K<nm 且不會重複描述一個被弄壞的格子。

輸出格式

對於每一個南瓜燈,輸出一行,如果這個南瓜燈能被做成工藝品,那麼輸出 "Yes",否則輸出 "No"。

樣例一

input

3
3 3 4
2 1
2 3
3 1
3 3
3 3 5
1 1
1 2
2 1
3 1
3 2
3 3 4
1 1
2 2
2 3
3 3

output

No
Yes
No

explanation

對於第一組數據,(1,1)(1,2) 有兩條簡單路徑,分別是 (1,1),(1,2)(1,1),(1,3),(1,2)

對於第三組數據,(1,2)(2,1) 不存在簡單路徑。

樣例二

見樣例數據下載。

限制與約定

對於所有數據,T10

測試點編號 n,m 的規模 K 的規模
1 n,m4 K105
2 n,m100
3
4 n,m1000
5
6 n,m109 K1000
7
8 K105
9
10

時間限制:1s

空間限制:256MB

經隊友介紹了這個比賽的OJ,想看看題目難度。按這個easy round看了一下第一題,表示當時沒細想被難住了。。。

這個題目就是給定一個類似迷宮的矩陣,有些地方是不能走的,左右邊界看作連通,上下邊界不連通,問能走的地方是不是任意兩個格子有且只有一條路徑連通。

當時一看數據我是傻了的。。這麼大怎麼搞。。

後來發現K最大100000是非常有用的,因爲如果n * m大於400000的話,肯定輸出的是No,因爲對於這樣一個左右連通的迷宮,必須有一整列是堵死的,不然左右肯定可以構成一條迴路,就GG了,所以大於400000以上的直接輸出No。

然後怎麼表示迷宮呢,很簡單,既然數不會大於400000,索性就開一個一維的數組來表示好了。一個block表示不能走的,一個vis表示走過的,任取一個可以走的點,進行DFS,只要發現DFS過程中出現重複走的情況,立刻判斷是有迴路的跳出,輸出No,如果最後dfs完遍歷的頂點並沒有達到所有的沒有阻礙的點的話,說明有兩個點之間沒有路徑,也輸出No,其他輸出Yes

代碼如下:

/*************************************************************************
	> File Name: A.cpp
	> Author: Zhanghaoran
	> Mail: [email protected]
	> Created Time: Thu 03 Dec 2015 12:30:42 AM CST
 ************************************************************************/

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#define pos(x, y) ((x - 1) * m + y)
using namespace std;

int T;
long n, m, K;
long x, y;
int block[410000];
int vis[410000];
bool flag = false;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int all;
void dfs(int x, int y, int lx, int ly){
    if(vis[pos(x, y)]){
        flag = true;
        return ;
    }

    all ++;
    vis[pos(x, y)] = 1;
    for(int i = 0; i < 4; i ++){
        int tempx = x + dx[i];
        int tempy = y + dy[i];
        if(tempy == m + 1)
            tempy = 1;
        if(tempy == 0)
            tempy = m;
        if(tempx == 0 || tempx == n + 1 || block[pos(tempx, tempy)] || (tempx == lx && tempy == ly))
            continue;
        dfs(tempx, tempy, x, y);
        if(flag)
            return ;
    }
}

int main(void){
    cin >> T;
    while(T --){
        cin >> n >> m >> K;
        if(n * m > 400000){
            for(int i = 0; i < K; i ++)
                scanf("%*d %*d");
            puts("No");
            continue;
        }
        flag = false;
        memset(vis, 0, sizeof(vis));
        memset(block, 0, sizeof(block));
        for(int i = 0; i < K; i ++){
            scanf("%d%d", &x, &y);
            block[pos(x, y)] = 1;
        }
        all = K;
        for(int i = 1; i <= n * m; i ++){
            if(!block[i] && !vis[i]){
                dfs((i - 1) / m + 1, (i - 1) % m + 1, -1, -1);
                break;
            }
        }
        if(all != n * m)
            flag = true;
        if(flag)
            puts("No");
        else 
            puts("Yes");
    }
    return 0;
}


發佈了136 篇原創文章 · 獲贊 15 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章