P10969 Katu Puzzle
2-SAT 基础练习题。
解法
先考虑每一条限制如何转化“如果谁……那么谁必须……”。
先把每个点拆成两个点,分别对应值为
那么问题来了:如果限制是
想一想我们在输出可行方案的时候是怎么做的。每次我们比较两个点
然后剩下就是判断
::::info[Code]
#include <bits/stdc++.h>
#define loop(i,a,b) for(int i=(a);~i;i=(b))
#define Mem(a,b) memset ((a),(b),sizeof((a)))
#define eb emplace_back
#define pb push_back
using namespace std;
typedef long long ll;
constexpr int N = 2e5 + 15;
namespace FAST_IO {
#define IOSIZE (1<<20)
char ibuf[IOSIZE], obuf[IOSIZE], *p1 = ibuf, *p2 = ibuf, *p3 = obuf;
#define getchar() ((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOSIZE,stdin),p1==p2)?(EOF):(*p1++))
#define putchar(x) ((p3==obuf+IOSIZE)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
#define isdigit(ch) (ch>47&&ch<58)
#define isspace(ch) (ch<33)
#define print(x,c) write(x),putchar(c),flush()
template <typename T> inline void read (T &x) { x = 0; T f = 1;char ch = getchar ();while (!isdigit (ch)) {if (ch == '-') f = -1; ch = getchar ();}while (isdigit (ch)) {x = (x << 1) + (x << 3) + (ch ^ '0'); ch = getchar ();} x *= f;}
template <> inline void read (double &x) { x = 0; int f = 1;char ch = getchar ();while (!isdigit (ch)) { if (ch == '-') f = -1; ch = getchar ();} while (isdigit (ch)) x = x * 10 + (ch - '0'), ch = getchar ();if (ch == '.') {ch = getchar (); for (double t = 0.1; isdigit (ch); t *= 0.1) x += t * (ch - '0'), ch = getchar ();}x *= f;}
inline bool read(char *s) { char ch; while (ch = getchar(), isspace(ch)); if (ch == EOF) return false; while (!isspace(ch)) *s++ = ch, ch = getchar(); *s = '\000'; return true; }
template <typename T, typename ...Args> inline void read (T &x, Args &...args) {read(x); read(args...);}
template <typename T> inline void write (T x) { if (x < 0) putchar ('-'), x = -x; if (x > 9) write (x / 10); putchar (x % 10 + 48);}
inline void write(char *x) { while (*x) putchar(*x++); }
inline void write(const char *x) { while (*x) putchar(*x++); }
inline void flush() { if (p3 != obuf) { fwrite(obuf, 1, p3 - obuf, stdout);p3 = obuf;}}
}
using namespace FAST_IO;
int n, m;
int head[N], to[N << 1], nxt[N << 1], idx;
int dfn[N], low[N], tmp, stk[N], top, id[N], scc;
bool in_stk[N];
void add (int u, int v) {
to[idx] = v;
nxt[idx] = head[u];
head[u] = idx ++;
}
void Tarjan (int u) {
dfn[u] = low[u] = ++ tmp;
stk[++ top] = u;
in_stk[u] = true;
loop (i, head[u], nxt[i]) {
int v = to[i];
if (!dfn[v]) {
Tarjan (v);
low[u] = min (low[u], low[v]);
} else if (in_stk[v]) low[u] = min (low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
int cur;
++ scc;
do {
cur = stk[top --];
id[cur] = scc;
in_stk[cur] = false;
} while (u != cur);
}
}
int main () {
Mem (head, -1);
read (n, m);
for (int i = 1; i <= m; ++ i) {
int u, v, w;
char s[3];
read (u, v, w, s);
++ u, ++ v;
if (*s == 'A') {
if (w == 1) add (u, u + n), add (v, v + n);
else add (u + n, v), add (v + n, u);
} else if (*s == 'O') {
if (w == 1) add (u, v + n), add (v, u + n);
else add (u + n, u), add (v + n, v);
} else {
if (w == 1) add (u, v + n), add (v, u + n), add (u + n, v), add (v + n, u);
else add (u, v), add (v, u), add (u + n, v + n), add (v + n, u + n);
}
}
for (int i = 1; i <= 2 * n; ++ i) {
if (!dfn[i]) Tarjan (i);
}
for (int i = 1; i <= n; ++ i) {
if (id[i] == id[i + n]) {
print ("NO", '\n');
return 0;
}
}
print ("YES", '\n');
return 0;
}
::::