
该模板来自大白书
【解释】
给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)”
每个变量和拆成两个点 2*i为假, 2*i+1为真
“Xi为真 或 Xj为真” 等价于 “Xi为假 –> Xj为真”。
DFS算法没有回溯过程。
【函数说明】
模板bfs函数在模板外一般用不到
void init(int n) :初始化
void add(int x,int xval,int y,int yval) :添加边,x,y为节点编号,xval=1表示真,xval=0表示假,yval同理
bool solve() :计算是否存在解。如果存在解返回true,不存在返回false
【变量说明】
vector<int>G[MAXN*2];//邻接表表示图。
bool mark[MAXN*2];//表示某个结点(不是变量)是否已经被访问
int s[MAXN*2],c;//s存储某次DFS访问过那些点。用于重新标记时消去之前访问过的点的记录(mark[]值)
struct Twosat
{
int n;
vector<int>G[MAXN*];
bool mark[MAXN*];
int s[MAXN*],c; bool dfs(int x)
{
if(mark[x^])return ;//如果x^1被标记过,说明x是不成立(x^1成立),返回0
if(mark[x])return ;//如果x被标记过,说明x是成立的,返回1
mark[x]=;
s[c++]=x;
for(int i=;i<G[x].size();i++)
{
if(!dfs(G[x][i]))return ;
}
return ;//与之相连的变量都满足。
} void init(int n)//初始化,n为变量个数(结点数2*n,从0开始)
{
this->n=n;
for(int i=;i<n*;i++)G[i].clear();
memset(mark,,sizeof(mark));
} void add(int x,int xval,int y,int yval)//添加边,xval=1表示真,xval=0表示假,yval同理
{
x=x*+xval;
y=y*+yval;
G[x^].push_back(y);
G[y^].push_back(x);
} bool solve()//计算。
{
for(int i=;i<n*;i+=)
{
if(!mark[i]&&!mark[i+])
{
c=;
if(!dfs(i))//如果”Xi为假”这个假定不成立
{
while(c>)mark[s[--c]]=;
if(!dfs(i+))return ;//改成”Xi为真”,重新标记。
}
}
}
return ;
}
}sat;