2-SAT
2-SAT
有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
因为一对夫妻中只有一个可以出席, 所以可以将女方出席看成命题 \(i_0\) 男方出席看成命题 \(i_1\) 然后两个命题护卫反命题
若 \(i_0\) 与 \(j_1\) 有矛盾, 并且 \(i_0\) 为真 那么 \(j_0\) 一定为真 反着同理
回到这个夫妻的问题
假如 \(a_0\) 和 \(b_0\) 有矛盾, 那么 \(a_0\) 一定连向 \(b_1\)
然后就可以形成一个图
考虑如果图上有环怎么办, 不用管
那么什么情况下不可以呢?
就是如果图上的一个强连通分量中同时有夫妻中的两个人
那么就意味着要想选\(A_0\)就必须选\(A_1\)显然不行
但是为什么必须要在同一个强连通分量中呢?
因为如果只是单纯的\(A_0\to ...\to A_1\)我们可以直接从\(A_1\)开始行走
为什么只要没有任何一对夫妻在同一个强连通分量中就成功了呢?
因为建立的图是矛盾的图, 不是总情况的图, 所以就意味着没有建立边的两个点是可以行走的, 所以只要不是矛盾就一定是联通的
代码(使用Kosaraju用来计算强连通分量)
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<climits>
#include<iomanip>
#include<vector>
using namespace std;
inline int read() {int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar();}while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;}
const int N=2000+5;
vector<int> G[N],rG[N];
void addEdge(int from,int to){
G[from].push_back(to);
rG[to].push_back(from);
}
int n,m,vis[N],sccno[N],cnt;
vector<int> S;
void dfs1(int u){
if(vis[u]) return;
vis[u]=1;
for(int i=0;i<G[u].size();i++) dfs1(G[u][i]);
S.push_back(u);
}
void dfs2(int u){
if(sccno[u]) return;
sccno[u] = cnt;
for(auto v:rG[u]) dfs2(v);
}
bool twoSAT(){
for(int i=1;i<=n;i++)
if(sccno[i]==sccno[i+n])
return false;
return true;
}
signed main() {
while( scanf("%d%d",&n,&m)!=EOF&&(n+m)){
// n=read(),m=read();
for(int i=0;i<=2*n;i++){
G[i].clear();
rG[i].clear();
}
cnt=0;memset(sccno,0,sizeof(sccno));memset(vis,false,sizeof(vis));S.clear();
while(m--) {
int x=read()+1,y=read()+1,xVal=read(),yVal=read();
if(xVal==0&&yVal==0){//x为0或y为0
addEdge(x+n,y);//x为0,y为1
addEdge(y+n,x);//y为0,x为1
}
else if(xVal==0&&yVal==1){//x为0或y为1
addEdge(x+n,y+n);//x为0,y为0
addEdge(y,x);//y为1,x为1
}
else if(xVal==1&&yVal==0){//x为1或y为0
addEdge(x,y);//x为1,y为1
addEdge(y+n,x+n);//y为0,x为0
}
else if(xVal==1&&yVal==1){//x为1或y为1
addEdge(x,y+n);//x为1,y为0
addEdge(y,x+n);//y为1,x为0
}
}
// for(int i=1;i<=2*n;i++){
// cout<<i<<": ";
// for(auto v:G[i]) cout<<v<<' ';
// cout<<endl;
// }
// for(int i=1;i<=2*n;i++){
// cout<<i<<": ";
// for(auto v:rG[i]) cout<<v<<' ';
// cout<<endl;
// }
for(int i=1;i<=2*n;i++) if(!vis[i]) dfs1(i);
// for(auto v:S) if(vis[v]) dfs2(v);
for(int i=2*n-1; i>=0; i--){
if(!sccno[S[i]]){
cnt++;
dfs2(S[i]);
}
}
// for()
bool flag=twoSAT();
if(!flag) printf("NO\n");
else printf("YES\n");
}
return 0;
}

浙公网安备 33010602011771号