这是我遇到的第一道2-SAT问题。将两条边记为x和y。如果x和y相交,那么x和y不能同时在环外(即都取true),也不能同时在环内(即都取false)。前者,我们有x->~y, y -> ~x;后者,我们有~x->y, ~y -> x。
这道题只问2-SAT是否能满足,而没有问怎样才能满足,所以只需要求强连通子图部分,而不需要逆向拓扑排序部分(这部分目前还不是很懂)。
thestoryofsnow | 3207 | Accepted | 1236K | 79MS | C++ | 3532B |
/*
ID: thestor1
LANG: C++
TASK: poj3207
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>
using namespace std;
// const int MAXN = 1000;
const int MAXM = 500;
class Edge
{
public:
int a, b;
Edge() {}
Edge(int a, int b) : a(a), b(b) {}
inline bool operator< (const Edge &rhs) const
{
return a < rhs.a || (a == rhs.a && b < rhs.b);
}
};
bool isundefined(int u, vector<int> &indexes)
{
return indexes[u] < 0;
}
void strongconnect(int u, int &index, vector<int> &indexes, vector<int> &lowlinks, int &SCCNO, vector<int> &sccnos, stack<int> &S, vector<bool> &onStack, const vector<vector<int> > &adjs)
{
// Set the depth index for u to the smallest unused index
indexes[u] = index;
lowlinks[u] = index;
index++;
S.push(u);
onStack[u] = true;
// Consider successors of u
for (int i = 0; i < adjs[u].size(); ++i)
{
int v = adjs[u][i];
if (isundefined(v, indexes))
{
// Successor v has not yet been visited; recurse on it
strongconnect(v, index, indexes, lowlinks, SCCNO, sccnos, S, onStack, adjs);
lowlinks[u] = min(lowlinks[u], lowlinks[v]);
}
else if (onStack[v])
{
// Successor v is in stack S and hence in the current SCC
lowlinks[u] = min(lowlinks[u], lowlinks[v]);
}
}
// If u is a root node, pop the stack and generate an SCC
if (indexes[u] == lowlinks[u])
{
// start a new strongly connected component
while (true)
{
int v = S.top();
S.pop();
onStack[v] = false;
// add v to current strongly connected component
sccnos[v] = SCCNO;
if (v == u)
{
break;
}
}
SCCNO++;
}
}
// Tarjan's strongly connected components algorithm
// See http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
void tarjan(const int N, const vector<vector<int> > &adjs, int &SCCNO, vector<int> &sccnos)
{
int index = 0;
vector<int> indexes(N, -1);
vector<int> lowlinks(N, -1);
stack<int> S;
vector<bool> onStack(N, false);
for (int u = 0; u < N; ++u)
{
if (isundefined(u, indexes))
{
strongconnect(u, index, indexes, lowlinks, SCCNO, sccnos, S, onStack, adjs);
}
}
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
Edge edges[MAXM];
for (int i = 0; i < m; ++i)
{
scanf("%d%d", &edges[i].a, &edges[i].b);
if (edges[i].a > edges[i].b)
{
int t = edges[i].a;
edges[i].a = edges[i].b;
edges[i].b = t;
}
}
sort(edges, edges + m);
// in the 2-SAT sense, if i is x, then i + n is ~x
vector<vector<int> > adjs(2 * m, std::vector<int>());
for (int i = 0; i < m; ++i)
{
for (int j = i + 1; j < m && edges[j].a < edges[i].b; ++j)
{
if (edges[j].b > edges[i].b)
{
// i interleaves with j, then x (i) and y (j) can not both be true
// then if x is true, y should be false (that is, ~y is true)
// x -> ~y
adjs[i].push_back(j + m);
adjs[j].push_back(i + m);
adjs[i + m].push_back(j);
adjs[j + m].push_back(i);
}
}
}
int SCCNO = 0;
vector<int> sccnos(2 * m, -1);
tarjan(2 * m, adjs, SCCNO, sccnos);
bool conflict = false;
for (int i = 0; i < m; ++i)
{
// if both x and ~x are true, we have conflicts here
if (sccnos[i] == sccnos[i + m])
{
conflict = true;
break;
}
}
if (conflict)
{
printf("the evil panda is lying again\n");
}
else
{
printf("panda is telling the truth...\n");
}
return 0;
}