ICPC Pacific Northwest Regional Contest 2016 - Illumination(2-SAT)

You inherited a haunted house. Its floor plan is an n-by-n square grid with l lamps in fixedlocations and no interior walls. Each lamp can either illuminate its row or its column, but not bothsimultaneously. The illumination of each lamp extends by r squares in both directions, so a lampunobstructed by an exterior wall of the house can illuminate as many as 2r + 1 squares. 

If a square is illuminated by more than one lamp in its row, or by more than one lamp in its column,the resulting bright spot will scare away ghosts forever, diminishing the value of your property. Isit possible for all lamps to illuminate a row or column, without scaring any ghosts? Note that asquare illuminated by two lamps, one in its row and the other in its column, will not scare awaythe ghosts.

Input

The first line of input contains three positive integers, n, r and l (1 ≤ n, r, l ≤ 1,000). 

Each of the next l lines contains two positive integers ri and ci (1 ≤ ri, ci ≤ n), indicating thatthere is a lamp in row ri and column ci. 

It is guaranteed that all lamps are in distinct locations.

Output

Print, on a single line, YES if it is possible to illuminate all lamps as stated above; otherwise, print NO.

樣例輸入1複製

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

樣例輸出1複製

YES

樣例輸入2複製

3 2 6
1 1
1 2
1 3
3 1
3 2
3 3

樣例輸出2複製

NO

題目鏈接:點擊查看

題目大意:給出一個 n * n 的二維平面,再給出 k 個燈塔,每個燈塔可以選擇照射當前行或者當前列,如果是照射當前行的話,可以照射 [ x - r , x + r ] 的範圍,如果是照射當前列的話,可以照射 [ y - r , y + r ] 的範圍,問是否存在一種照射情況,使得沒有任何一個格子被相同方向的燈塔照射兩次及以上

題目分析:2-SAT模板問題,每個燈塔有橫着和豎着兩種方向選擇,所以可以 n * n 枚舉任意兩個燈塔,如果這兩個燈塔同時橫着放有衝突的話,那麼就說明一個橫着時,另一個必須豎着,對於豎着有衝突的話同理,建好圖之後套上 tarjan 的模板就好了

代碼:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=2e3+100;

const int M=2e6+100;

struct Point
{
	int x,y;
}p[N];
 
struct Egde
{
	int to,next;
}edge1[M];
 
int head1[N],low[N],dfn[N],c[N],Stack[N],num,cnt,cnt1,dcc,n,r,top,m;
 
bool ins[N];
 
vector<int>scc[N];
 
void addedge1(int u,int v)
{
	edge1[cnt1].to=v;
	edge1[cnt1].next=head1[u];
	head1[u]=cnt1++;
}
 
void tarjan(int u)
{
	dfn[u]=low[u]=++num;
	Stack[++top]=u;
	ins[u]=true;
	for(int i=head1[u];i!=-1;i=edge1[i].next)
	{
		int v=edge1[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(ins[v])
			low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u])
	{
		cnt++;
		int v;
		do
		{
			v=Stack[top--];
			ins[v]=false;
			c[v]=cnt;
			scc[cnt].push_back(v);
		}while(u!=v);
	}
}
 
void solve()
{
	for(int i=1;i<=2*n;i++)//縮點 
		if(!dfn[i])
			tarjan(i);
}
 
void init()
{
	for(int i=0;i<N;i++)
		scc[i].clear();
	top=cnt=cnt1=num=dcc=0;
	memset(head1,-1,sizeof(head1));
	memset(low,0,sizeof(low));
	memset(dfn,0,sizeof(dfn));
	memset(c,0,sizeof(c));
	memset(ins,false,sizeof(ins));
}
 
bool check()
{
	for(int i=1;i<=n;i++)
		if(c[i]==c[i+n])
			return false;
	return true;
}

int meet(int i,int j,int r)
{
	if(p[i].x==p[j].x)
	{
		if(abs(p[i].y-p[j].y)<=2*r)
			return 1;
	}
	if(p[i].y==p[j].y)
	{
		if(abs(p[i].x-p[j].x)<=2*r)
			return 2;
	}
	return 0;
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	init();
	scanf("%d%d%d",&m,&r,&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&p[i].x,&p[i].y);
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
		{
			int temp=meet(i,j,r);
			if(temp==1)
			{
				addedge1(i,j+n);
				addedge1(j,i+n);
			}
			else if(temp==2)
			{
				addedge1(i+n,j);
				addedge1(j+n,i);
			}
		}
	solve();
	if(check())
		puts("YES");
	else
		puts("NO");




















    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章