首页 > 代码库 > 2-SAT入门
2-SAT入门
大概学了一下2-SAT,写了一道模板和一道USACO
输出一个方案的话,tarjan缩点后倒着拓扑,染色输出。
求任何解下选哪个就得枚举每个点dfs来判断选哪个。
HIT 1917(2-sat模板)
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=16010,inf=1e9;
struct poi{int too,pre,x;}e[maxn*10],e2[maxn*10];
int last[maxn],last2[maxn],dfn[maxn],low[maxn],col[maxn],lack[maxn],ru[maxn],rs[maxn],st[maxn],op[maxn];
int n,m,x,y,z,tot,tot2,tott,top,color,flag;
void read(int &k)
{
int f=1;k=0;char c=getchar();
while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
int next(int x){return x&1?x+1:x-1;}
void tarjan(int x)
{
dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
for(int i=last[x];i;i=e[i].pre)
if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
}
void topsort()
{
top=0;for(int i=1;i<=color;i++)if(!ru[i])st[++top]=i;
while(top)
{
int now=st[top--];
if(!rs[now])rs[now]=1,rs[op[now]]=2;
for(int i=last2[now];i;i=e2[i].pre)
if(!(--ru[e2[i].too]))st[++top]=e2[i].too;
}
}
void clr()
{
color=top=tot=tot2=flag=0;
memset(col,0,sizeof(col));
memset(dfn,0,sizeof(dfn));
memset(ru,0,sizeof(ru));
memset(rs,0,sizeof(rs));
memset(lack,0,sizeof(lack));
memset(last,0,sizeof(last));
memset(last2,0,sizeof(last2));
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
clr();
for(int i=1;i<=m;i++)read(x),read(y),add(x,next(y)),add(y,next(x));
for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)if(col[i<<1]==col[next(i<<1)]){printf("NIE\n");flag=1;break;}
else op[col[i<<1]]=col[next(i<<1)],op[col[next(i<<1)]]=col[i<<1];
if(flag)continue;
for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].too],col[e[i].x]),ru[col[e[i].x]]++;
topsort();
for(int i=1;i<=n;i++)if(rs[col[(i<<1)]]==1)printf("%d\n",i<<1);else printf("%d\n",next(i<<1));
}
return 0;
}
bzoj 2199
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=500010;
struct poi{int x,too,pre;}e[maxn],e2[maxn];
int n,m,t,tot,tot2,tott,top,color;
int dfn[maxn],low[maxn],col[maxn],last[maxn],last2[maxn],v[maxn],st[maxn],lack[maxn];
char ans[maxn];
void read(int &k)
{
int f=1;k=0;char c=getchar();
while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
k*=f;
}
int readd()
{
int x;read(x);char c=getchar();
while(c!=‘Y‘&&c!=‘N‘)c=getchar();
if(c==‘Y‘)return (x<<1)^1;
return x<<1;
}
void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
void dfs(int x)
{
v[x]=t;
for(int i=last2[x];i;i=e2[i].pre)
if(v[e2[i].too]!=t)dfs(e2[i].too);
}
bool check(int x)
{
t++;dfs(x);
for(int i=1;i<=n;i++)
if(v[col[(i<<1)^1]]==t&&v[col[i<<1]]==t)return 0;
return 1;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
for(int i=last[x];i;i=e[i].pre)
if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
}
void dfss(int x)
{
v[x]=1;
for(int i=last[x];i;i=e[i].pre)
if(!v[e[i].too])dfss(e[i].too);
}
int main()
{
read(n);read(m);
for(int i=1;i<=m;i++)
{
int x=readd(),y=readd();
add(x^1,y);add(y^1,x);
}
for(int i=2;i<=((n<<1)^1);i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)if(col[(i<<1)^1]==col[i<<1]){puts("IMPOSSIBLE");return 0;}
for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].x],col[e[i].too]);
for(int i=1;i<=n;i++)
{
int x=check(col[(i<<1)^1]),y=check(col[i<<1]);
if(!(x||y)){puts("IMPOSSIBLE");return 0;}
else if(x&&y)ans[i]=‘?‘;
else if(x)ans[i]=‘Y‘;
else if(y)ans[i]=‘N‘;
}
for(int i=1;i<=n;i++)putchar(ans[i]);
}
2-SAT入门
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。