题目
https://vjudge.net/problem/Gym-101201F
题意
给你n个点 问你能不能符合条件
条件: 1 每个点选择行或列 会照亮左右或上下r个格子
2 某个点不能被两个同行或同列灯照亮
思路
2-sat模板题
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4+100;
struct node
{
int x,y;
}a[maxn];
vector<int> G[maxn];
int dfn[maxn],low[maxn];
int vis[maxn],col[maxn];
int sta[maxn];
int color,cnt,tot;
int n,m;
void tarjan(int u) //模板
{
cnt++;
dfn[u]=low[u]=cnt;
vis[u]=1;
sta[++tot]=u;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i];
if(dfn[v]==-1)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
color++;
col[u]=color;
vis[u]=0;
while(sta[tot]!=u)
{
col[sta[tot]]=color;
vis[sta[tot]]=0;
tot--;
}
tot--;
}
}
int two_sat()
{
memset(dfn,-1,sizeof(dfn));
for(int i=0; i< n<<1; i++) //模板
{
if(dfn[i]==-1)
{
tarjan(i);
}
}
for(int i=0; i<n; i++) //模板
{
int x = i<<1;
int y = i<<1|1;
if(col[i<<1]==col[i<<1|1])
{
return 0;
}
}
return 1;
}
int main()
{
int l,r;
cnt = tot = color = 0;
scanf("%d%d%d",&l,&r,&n);
for(int i = 0;i < n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
for(int i = 0;i < n;i++)
{
for(int j = i + 1;j < n;j++)
{
if(a[i].x == a[j].x&&(a[i].y - a[j].y) < 2*r)
{
G[i*2].push_back(j*2+1);
G[j*2].push_back(i*2+1);
}
if(a[i].y == a[j].y&&(a[i].x - a[j].x) < 2*r)
{
G[i*2+1].push_back(j*2);
G[j*2+1].push_back(i*2);
}
}
}
if(two_sat()) printf("YES\n");
else printf("NO\n");
return 0;
}