题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3062
题解:
Tarjan缩点后,观察是否有夫妻同时被染上了同一种颜色,有就NO没有就YES。
贴一下自己学习2 - SAT时看的大神博客:
http://blog.csdn.net/jarjingx/article/details/8521690
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
vector <int> mapp[2500];
int dfn[2500],low[2500],stk[2500],vis[2500],color[2500];
int cnt,t,sig;
int n,m,a,b,c,d,x1,y1,x2,y2;
void init()
{
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(color,0,sizeof(color));
memset(stk, 0, sizeof(stk));
for(int i=1;i<=2*n;i++)mapp[i].clear();
}
void Tarjan(int u)
{
vis[u] = 1;
low[u] = dfn[u] = cnt++;
stk[++t] = u;
for(int i = 0; i < mapp[u].size(); i++)
{
int v = mapp[u][i];
if(!vis[v]) Tarjan(v);
if(vis[v] == 1) low[u] = min(low[u],low[v]);
}
if(dfn[u] == low[u])
{
sig++;
do
{
color[stk[t]] = sig;
vis[stk[t]] = -1;
}
while(stk[t--] != u);
}
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
init();
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d%d", &a, &b, &c, &d);
x1 = 2 * a + 1 + c;
y1 = 2 * b + 1 + d;
x2 = 2 * a + 2 - c;
y2 = 2 * b + 2 - d;
mapp[x1].push_back(y2);
mapp[y1].push_back(x2);
}
cnt = 1, t = -1, sig = 0;
for(int i = 1; i <= 2*n; i++)
{
if(!vis[i])
Tarjan(i);
}
//for(int i = 1; i <= 2*n; i++)
// cout << i << " " <<color[i] <<endl;
bool flag=true;
for(int i = 0; i < n; i++ )
{
if(color[2*i + 1]==color[2*i + 2])
{
flag=false;
break;
}
}
if(flag)
puts("YES");
else
puts("NO");
}
return 0;
}