#include "iostream"
#include "stack"
#include "vector"
#include "string.h"
using namespace std;
const MAX_V = 100;
vector<int> G[MAX_V]; //图的邻接表
vector<int> rG[MAX_V]; //反向图的邻接表
int visit[MAX_V]; //访问标记
int cmp[MAX_V]; //所属强连通分量的拓扑排序
vector<int> vs; //后序遍历的顶点列表
int V; //顶点数
void addEdge(int from, int to)
{
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v)
{
visit[v] = 1;
for(int i=0; i<G[v].size(); i++)
if(!visit[G[v][i]])
dfs(G[v][i]);
vs.push_back(v);
}
void rdfs(int v, int k)
{
visit[v] = 1;
cmp[v] = k;
for(int i=0; i<rG[v].size(); i++)
if(!visit[rG[v][i]])
rdfs(rG[v][i], k);
}
int scc()
{
memset(visit, 0, sizeof(visit));
vs.clear();
int i;
for(i=0; i<V; i++)
if(!visit[i])
dfs(i);
memset(visit, 0, sizeof(visit));
int k = 0;
for(i=vs.size()-1; i>=0; i--) //越是尾部的结点编号越小
if(!visit[vs[i]])
rdfs(vs[i], k++);
return k;
}
int main()
{
//布尔公式为(a∨¬b)∧(b∨c)∧(¬c∨¬a)
V = 6; //6个顶点 a, b, c, ¬a, ¬b, ¬c
// 0, 1, 2, 3, 4, 5
//a∨¬b = (¬a→¬b)∧(b→a)
addEdge(3, 4); addEdge(1, 0);
//b∨c = (¬b→c)∧(¬c→b)
addEdge(4, 2); addEdge(5, 1);
//¬c∨¬a = (c→¬a)∧(a→¬c)
addEdge(2, 3); addEdge(0, 5);
scc(); //强连通分量分解
int i;
for(i=0; i<3; i++)
{
if(cmp[i] == cmp[i+3]) //x与¬x在同一个强连通分量中
{
cout << "No";
return 0;
}
}
//给出一组解
for(i=0; i<3; i++)
{
if(cmp[i] > cmp[i+3]) //假设当x所在连通分量的拓扑排序在¬x之前,即标号较大,x为真
cout << "true" << " ";
else
cout << "false" << " ";
}
cout << endl;
return 0;
}
2-SAT
最新推荐文章于 2022-08-02 16:18:19 发布