CodeForces 750H. New Year and Snowy Grid

Pay attention to the output section below, where you will see the information about flushing the output.

Bearland is a grid with h rows and w columns. Rows are numbered 1 through h from top to bottom. Columns are numbered 1 through wfrom left to right. Every cell is either allowed (denoted by '.' in the input) or permanently blocked (denoted by '#').

Bearland is a cold land, where heavy snow often makes travelling harder. Every day a few allowed cells are temporarily blocked by snow. Note, that this block works only on this particular day and next day any of these cells might be allowed again (unless there is another temporarily block).

It's possible to move directly between two cells only if they share a side and none of them is permanently or temporarily blocked.

Limak is a little polar bear who lives in Bearland. His house is at the top left cell, while his school is at the bottom right cell. Every day Limak should first go from his house to the school and then return back to his house. Since he gets bored easily, he doesn't want to visit the same cell twice on one day, except for the cell with his house, where he starts and ends. If Limak can reach a school and return home avoiding revisiting cells, he calls a day interesting.

There are q days you must process, one after another. For each of these days you should check if it's interesting and print "YES" or "NO" on a separate line. In order to be able to read the description of the next day you should print the answer for the previous one and flush the output.

It's guaranteed that a day with no cells temporarily blocked by snow would be interesting. It's also guaranteed that cells with Limak's house and school are never blocked (neither permanently or temporarily).

Input

The first line of the input contains three integers hw and q (2 ≤ h, w ≤ 10001 ≤ q ≤ 10 000) — the height and the width of the grid, and the number of days, respectively.

Next h lines describe which cells are allowed and which permanently blocked. The i-th line contains a string of length w, describing the i-th row. Every character is either '.' (denoting an allowed cell) or '#' (denoting a permanently blocked cell). It's guaranteed that a day with no cells temporarily blocked by snow would be interesting.

Then, the description of q days is given. The description of the i-th day starts with a line containing a single integer ki (1 ≤ ki ≤ 10) — the number of cells that are temporarily blocked by snow on that day. Each of next ki lines contains two integers ri, j and ci, j (1 ≤ ri, j ≤ h1 ≤ ci, j ≤ w), representing a cell at the intersection of the row ri, j and the column ci, j. The given ki cells are distinct and none of them is permanently blocked. Also, none of them contains Limak's house or school.

Output

For each of q days print "YES" if that day is interesting, and otherwise print "NO", both without the quotes. After printing an answer, you have to both print the end-of-line character and flush the output. Then you can proceed to the next day. You can get Idleness Limit Exceeded if you don't print anything or if you forget to flush the output.

To flush you can use (just after printing a YES/NO and end-of-line):

  • fflush(stdout) in C++;
  • System.out.flush() in Java;
  • stdout.flush() in Python;
  • flush(output) in Pascal;
  • See the documentation for other languages.
Examples
input
3 5 4
.....
.....
.#...
1
1 4
1
1 5
2
2 4
3 1
2
1 5
3 3
output
NO
YES
YES
NO
input
9 31 5
...............................
...............................
.###.###.#.###...###.###.#.###.
...#.#.#.#.#.......#.#.#.#...#.
.###.#.#.#.###...###.#.#.#...#.
.#...#.#.#.#.#...#...#.#.#...#.
.###.###.#.###...###.###.#...#.
...............................
...............................
5
6 5
2 11
1 14
8 15
2 14
5
2 14
1 14
8 16
6 5
2 11
3
2 2
1 4
8 30
10
3 1
3 11
5 16
7 21
4 16
3 5
7 31
3 9
7 25
3 27
10
3 1
3 9
7 25
3 27
7 21
4 17
3 5
7 31
4 16
3 11
output
NO
YES
YES
YES
NO
Note

In the first sample, there are 4 days. Drawings below show how Limak could go to school and return to his home in the second and the third day (on the left and on the right respectively). A permanently blocked cell is painted red, while cells temporarily blocked by snow are painted orange. Black and green arrows should Limak's way to the school and back to the house respectively.

For the second sample, below you can see how the grid looks like on each day, where '#' denotes a cell that is blocked, either temporarily or permanently.


题意:给一个N*M的棋盘,有障碍,Q次询问把K个点变成障碍能否找到两条(1,1)到(n,n)的不相交路径,强制在线

题解:

并查集

本质上是找最大流是否大于等于2,那么我们可以转对偶图,即从左下到右上的最短路,障碍点权为0,空地为1

找一条路径很好做,直接并查集判连通即可,而找两条路径就是判是否存在一个点使得把它变成障碍S到T连通

那么我们先预处理并查集,然后每次暴力把那K个点的周围的点提取出来判一判就好了

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define fill( x, y ) memset( x, y, sizeof x )
#define copy( x, y ) memcpy( x, y, sizeof x )
using namespace std;

typedef long long LL;
typedef pair < int, int > pa;

const int MAXN = 1005;
const int MAXM = 1000005;
const int dx[] = { 1, 1, 1, 0, 0, -1, -1, -1 };
const int dy[] = { 1, 0, -1, 1, -1, 1, 0, -1 };

int fa[MAXM], id_cnt, id[MAXN][MAXN], S, T, n, m, Q, st[MAXN], top, cnt, blkx[MAXN], blky[MAXN];
char ch[MAXN][MAXN];
bool haveans = 1;
set < pa > s;

inline int find(int x) { return fa[ x ] == x ? x : fa[ x ] = find( fa[ x ] ); }
inline int find2(int x) { return fa[ x ] == x ? x : find2( fa[ x ] ); }
inline void merge(int x, int y) { fa[ find2( x ) ] = fa[ find2( y ) ]; }
inline pa make(int x, int y) { return mp( min( x, y ), max( x, y ) ); }

int main()
{
#ifdef wxh010910
	freopen( "data.in", "r", stdin );
#endif
	scanf( "%d%d%d", &n, &m, &Q );
	for( int i = 1 ; i <= n ; i++ ) scanf( "%s", ch[ i ] + 1 );
	for( int i = 1 ; i <= n ; i++ ) for( int j = 1 ; j <= m ; j++ ) id[ i ][ j ] = ++id_cnt;
	S = ++id_cnt; T = ++id_cnt;
	for( int i = 1 ; i <= id_cnt ; i++ ) fa[ i ] = i;
	for( int i = 1 ; i <= n ; i++ ) id[ i ][ 0 ] = S, id[ i ][ m + 1 ] = T, ch[ i ][ 0 ] = ch[ i ][ m + 1 ] = '#';
	for( int i = 1 ; i <= m ; i++ ) id[ 0 ][ i ] = T, id[ n + 1 ][ i ] = S, ch[ 0 ][ i ] = ch[ n + 1 ][ i ] = '#';
	for( int i = 1 ; i <= n ; i++ )
		for( int j = 1 ; j <= m ; j++ ) if( ch[ i ][ j ] == '#' )
			for( int k = 0 ; k < 8 ; k++ )
			{
				int x = i + dx[ k ], y = j + dy[ k ];
				if( ch[ x ][ y ] == '#' ) fa[ find( id[ i ][ j ] ) ] = find( id[ x ][ y ] );
			}
	for( int i = 1 ; i <= id_cnt ; i++ ) find( i );
	for( int i = 1 ; i <= n ; i++ )
		for( int j = 1 ; j <= m ; j++ )
		{
			if( i == 1 && j == 1 ) continue;
			if( i == n && j == m ) continue;
			for( int k = 0 ; k < 8 ; k++ )
				for( int l = k + 1 ; l < 8 ; l++ )
				{
					s.insert( make( find( id[ i + dx[ k ] ][ j + dy[ k ] ] ), find( id[ i + dx[ l ] ][ j + dy[ l ] ] ) ) );
					if( make( find( id[ i + dx[ k ] ][ j + dy[ k ] ] ), find( id[ i + dx[ l ] ][ j + dy[ l ] ] ) ) == mp( find( S ), find( T ) ) ) haveans = false, i = n + 1, j = m + 1 ;
				}
		}
	if( !haveans ) { while( Q-- ) puts( "NO" ); return 0; }
	while( Q-- )
	{
		scanf( "%d", &cnt );
		for( int i = 1 ; i <= cnt ; i++ )
		{
			scanf( "%d%d", &blkx[ i ], &blky[ i ] ), ch[ blkx[ i ] ][ blky[ i ] ] = '#'; st[ ++top ] = find( id[ blkx[ i ] ][ blky[ i ] ] );
			for( int k = 0 ; k < 8 ; k++ )
				if( ch[ blkx[ i ] + dx[ k ] ][ blky[ i ] + dy[ k ] ] == '#' ) st[ ++top ] = find( id[ blkx[ i ] + dx[ k ] ][ blky[ i ] + dy[ k ] ] );
		}
		st[ ++top ] = find( S ), st[ ++top ] = find( T ); sort( st + 1, st + top + 1 ); top = unique( st + 1, st + top + 1 ) - st - 1;
		for( int i = 1 ; i <= cnt ; i++ )
			for( int k = 0 ; k < 8 ; k++ )
				if( ch[ blkx[ i ] + dx[ k ] ][ blky[ i ] + dy[ k ] ] == '#' ) merge( id[ blkx[ i ] + dx[ k ] ][ blky[ i ] + dy[ k ] ], id[ blkx[ i ] ][ blky[ i ] ] );
		bool ans = true;
		for( int i = 1 ; i <= top && ans ; i++ ) if( find2( st[ i ] ) == find2( S ) )
			for( int j = 1 ; j <= top && ans ; j++ ) if( find2( st[ j ] ) == find2( T ) && s.find( make( st[ i ], st[ j ] ) ) != s.end() )
				ans = false;
		puts( ans ? "YES" : "NO" ); fflush( stdout );
		for( int i = 1 ; i <= cnt ; i++ ) ch[ blkx[ i ] ][ blky[ i ] ] = '.';
		while( top ) fa[ st[ top ] ] = st[ top ], top--;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值