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: chilumanxi@xiyoulinux.org
	> 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;
}


posted @ 2015-12-03 01:54  ChiLuManXi  阅读(270)  评论(0编辑  收藏  举报