UVA Live 7957 (Gym 101201F) Illumination 2-SAT

来源:互联网 发布:专业电气制图软件 编辑:程序博客网 时间:2024/05/16 19:07

https://icpcarchive.ecs.baylor.edu/external/79/7957.pdf


7957 Illumination
You inherited a haunted house. Its floor plan is ann × nsquare grid with l
lamps in fxed locations and no interior walls. Each lamp can either illuminate
its row or its column, but not both simultaneously. The illumination of each
lamp extends by
r squares in both directions, so a lamp unobstructed 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. Is it possible for all lamps to
illuminate a row or column, without scaring any ghosts? Note that a square
illuminated by two lamps, one in its row and the other in its column, will not
scare away the ghosts.


Input
The input fle contains several test cases, each of them as described below.
The frst line contains three positive integers,
n,r and l(1 n; r; l 1; 000,l n2).
Each of the next
l lines contains two positive integersri andci (1ri; cin), indicating that there
is a lamp in row
riand column ci.
It is guaranteed that all lamps are in distinct locations.


Output
For each test case, print, on a single line, ‘YES’ if it is possible to illuminate all lamps as stated above;
otherwise, print ‘
NO’.


一个n*n的房子,有很多灯,每个格子只能被上下方向照一次、左右方向照一次,每个灯可以选择上下或是左右照,照明长度以自身位置为中心,占用2*r+1个格子。问能否安排一种方案,使所有格子满足条件。


经典2-SAT问题,把横照和竖照看做两个状态,对于格子A,一个是A,一个是A'.

因为每个格子可以同时在横向和竖向各照一次,所以行列都不同的灯之间其实并没有关系。

若某两个格子列相同,则其中一个为横向另一个必须是纵向,反之亦然。连边A->B',B->A'.

若某两个格子行相同,则其中一个为纵向另一个必须是横向,反之亦然。连边A'->B,B'->A.

建好图之后直接dfs就可以。


#include <cstdio>#include <iostream>#include <string.h>#include <string> #include <map>#include <queue>#include <vector>#include <set>#include <algorithm>#include <math.h>#include <cmath>#include <stack>#define mem0(a) memset(a,0,sizeof(a))#define meminf(a) memset(a,0x3f,sizeof(a))using namespace std;typedef long long ll;typedef long double ld;const int maxn=1005,maxk=2000005,inf=0x3f3f3f3f;  const ll llinf=0x3f3f3f3f3f3f3f3f;   const ld pi=acos(-1.0L); int color[maxn*2],x[maxn],y[maxn],head[maxn*2],dfn[maxn*2];int num;struct Edge {int from,to,pre;};Edge edge[maxk];void addedge(int from,int to) {edge[num]=(Edge){from,to,head[from]};head[from]=num++;}bool dfs(int now) {if (color[now]==1) return true;if (color[now]==2) return false;color[now]=1;color[now^1]=2;dfn[++num]=now;for (int i=head[now];i!=-1;i=edge[i].pre) {int to=edge[i].to;if (!dfs(to)) return false;}return true;}int main() {int n,r,l,i,j;num=0;memset(head,-1,sizeof(head));scanf("%d%d%d",&n,&r,&l);for (i=0;i<l;i++) {scanf("%d%d",&x[i],&y[i]);for (j=0;j<i;j++) {if (x[i]==x[j]) {if (abs(y[i]-y[j])<=2*r) addedge(j*2,(i*2)^1),addedge(i*2,(j*2)^1);} else if (y[i]==y[j]) {if (abs(x[i]-x[j])<=2*r) addedge((j*2)^1,i*2),addedge((i*2)^1,j*2);}}}/*for (i=0;i<num;i++) {if (edge[i].from%2==0) cout << edge[i].from/2+1;     else cout << edge[i].from/2+1 << '*'; cout << "  ";if (edge[i].to%2==0) cout << edge[i].to/2+1;     else cout << edge[i].to/2+1 << '*'; cout << "\n";}*/mem0(color);for (i=0;i<l;i++) {if (!color[i*2]) {num=0;if (!dfs(i*2)) {for (j=1;j<=num;j++) color[dfn[j]]=color[dfn[j]^1]=0;if (!dfs(i*2+1)) {    printf("NO");    return 0;    }}}}printf("YES");return 0;}