专栏文章
2-SAT(记录)
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipsr9tm
- 此快照首次捕获于
- 2025/12/03 17:20 3 个月前
- 此快照最后确认于
- 2025/12/03 17:20 3 个月前
2-SAT
① 是指一类题型
——在对数中在每两对的两个数中选一个是否可以满足选够个数
(1)例如以下问题
(一)建图分析

假设存在这样一组矛盾关系
我们就可以建两条有向边
(1)
(2)
(二)判断解是否存在
(三)转化题目
CPP
\
(四)奉上Code
#include<bits/stdc++.h>
#define N 2500
#define M 1000000
using namespace std;
int n,m,cnt=0,b=0,top=0,ans=0;
int s[N],ins[N],dfn[N],low[N],scc[N];
vector<int>v[N<<1];
int read();
int wf(int u){return u<<1;}
int hs(int u){return u<<1|1;}
void tarjan(int u);
void add(int from,int to){v[from].push_back(to);}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n>>m){
for(int i=1;i<=m;i++){
//int a1=read(),a2=read(),c1=read(),c2=read();
int a1,a2,c1,c2;
cin>>a1>>a2>>c1>>c2;
int f=(c1?hs(a1):wf(a1)),s=(c2?hs(a2):wf(a2));
add(f,(s^1));
add(s,(f^1));
}
for(int i=0;i<(n<<1);i++){
if(dfn[i])continue;
tarjan(i);
}
for(int i=0;i<(n<<1);i+=2){
if(scc[i]==scc[i^1]){
b=1;
break;
}
}
if(!b)cout<<"YES\n";
else cout<<"NO\n";
cnt=0,ans=0,b=0;
for(int i=0;i<(n<<1);i++)dfn[i]=0;
for(int i=0;i<(n<<1);i++)ins[i]=0;
for(int i=0;i<(n<<1);i++)v[i].clear();
}
return 0;
}
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return x*f;
}
void tarjan(int u){
low[u]=dfn[u]=++cnt;
ins[u]=1;
s[++top]=u;
for(int i=0;i<v[u].size();i++){
int g=v[u][i];
if(!dfn[g]){//Q1,u->g
tarjan(g);
low[u]=min(low[u],low[g]);
}
else if(ins[g]){//Q2,u->g
low[u]=min(low[u],dfn[g]);//Q3,u->g
}
}
if(dfn[u]==low[u]){
++ans;
while(1){
scc[s[top]]=ans;
ins[s[top]]=0;
if(s[top--]==u)break;//Q4,->top位置不对
}
}
return ;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...
