2-SAT问题
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2-SAT问题相关的知识,希望对你有一定的参考价值。
P4782 【模板】2-SAT 问题
在拓扑序上的表现为:我们要在两种取值中选择拓扑序较大的那个值;
越靠近叶节点的那些节点在 TarjanTarjan 的时候是越早被缩点的,所以拓扑序越大的点其所在强联通分量编号越小
强联通分量编号越小 -> 拓扑序越大 -> 越优
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e7+5;
int n,m,head[maxn],nxt[maxn],vi[maxn],cnt,tim;
int dfn[maxn],low[maxn],inq[maxn],tol,ans,belong[maxn];
void add(int from,int to)
vi[++cnt]=to;
nxt[cnt]=head[from];
head[from]=cnt;
stack<int>q;
void tarjan(int u)
dfn[u]=low[u]=++tim;
q.push(u);
inq[u]=1;
for(int i=head[u];i;i=nxt[i])
int v=vi[i];
if(!dfn[v])
tarjan(v);
low[u]=min(low[u],low[v]);
else if(inq[v])
low[u]=min(low[u],dfn[v]);
if(dfn[u]==low[u])
tol++;int tmp;
do
tmp=q.top();q.pop();
inq[tmp]=0;
belong[tmp]=tol;
while(tmp!=u);
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
int a,x,b,y;scanf("%d%d%d%d",&a,&x,&b,&y);
if(x==0&&y==0)
add(a+n,b);
add(b+n,a);
if(x==0&&y==1) //a=0 or b=1
add(a+n,b+n);
add(b,a);
if(x==1&&y==0)
add(a,b);
add(b+n,a+n);
if(x==1&&y==1)
add(a,b+n);
add(b,a+n);
for(int i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
if(belong[i]==belong[i+n])
cout<<"IMPOSSIBLE"<<endl;;
return 0;
cout<<"POSSIBLE"<<endl;
for(int i=1;i<=n;i++)
if(belong[i]>belong[i+n])
cout<<"1 ";
else
cout<<"0 ";
cout<<endl;
return 0;
P4171 [JSOI2010] 满汉全席
#include <bits/stdc++.h>
using namespace std;
const int maxn=400;
int t,n,m;
struct node
int v,nxt;
E[4010];
int head[maxn],tot;
int low[maxn],dfn[maxn],cnt;
int col[maxn],ins[maxn],colnum;
stack<int> st;
char s1[5],s2[5];
void add(int u,int v)
E[++tot].nxt=head[u];
E[tot].v=v;
head[u]=tot;
void tarjan(int u)
low[u]=dfn[u]=++cnt;
st.push(u); ins[u]=1;
for(int i=head[u];i;i=E[i].nxt)
int v=E[i].v;
if(!dfn[v]) tarjan(v); low[u]=min(low[u],low[v]);
else if(ins[v])
low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u])
int v; colnum++;
do
v=st.top();
st.pop(); ins[v]=0;
col[v]=colnum;
while(v!=u);
void init()
tot=cnt=colnum=0;
memset(head,0,sizeof(head));
memset(col,0,sizeof(col));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
int main()
cin>>t;
while(t--)
init();
cin>>n>>m;
for(int i=1;i<=m;++i)//h-1,m-0
string s1,s2;cin>>s1>>s2;
int a=0,b=0,k;
k=1; while(s1[k]>='0'&&s1[k]<='9')a=a*10+s1[k++]-'0';
k=1; while(s2[k]>='0'&&s2[k]<='9')b=b*10+s2[k++]-'0';
if(s1[0]=='m'&&s2[0]=='m')
add(a+n,b);
add(b+n,a);
else if(s1[0]=='m'&&s2[0]=='h') //a=0 or b=1
add(a+n,b+n);
add(b,a);
else if(s1[0]=='h'&&s2[0]=='m')
add(a,b);
add(b+n,a+n);
else if(s1[0]=='h'&&s2[0]=='h')
add(a,b+n);
add(b,a+n);
for(int i=1;i<=n<<1;++i)
if(!dfn[i])tarjan(i);
int judge=0;
for(int i=1;i<=n;++i)
if(col[i]==col[i+n])
judge=1;break;
if(judge)
printf("BAD\\n");
else
printf("GOOD\\n");
return 0;
以上是关于2-SAT问题的主要内容,如果未能解决你的问题,请参考以下文章