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复制

扫描二维码关注公众号,回复: 11366146 查看本文章
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;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106894421