Foreword
Since konjac has just started to learn \ (\ text {2-SAT} \) , so the solution to a problem in some places may not be refined, looking bear with me!
Title Description
Title simply means the standard \ (\ text {2-SAT } \) problem model. So we will first introduce \ (\ text {2-SAT} \) (The following is a personal little generalization)
\ (\ text {2-SAT} \) issue, abstract it, is this:
given \ (n-\) boolean variables \ (\ {x_n \} \) , and \ (m \) proposition \ ((a, AA, B, BB) \) , a proposition is valid when \ ([X_a = aa] \ lor [x_b =
bb] \) is now determined whether a solution to the \ (\ {x_n \} \ ) in assigning a value to each element, all the \ (m \) proposition set up
for this issue, we look at ways to build model diagram:
for \ (n \) different variables \ (x \) , we will split it into two points, respectively, \ (x \) is true and \ (X \) is false (can \ (I \) represents \ (x_i \) is true, \ (n-I + \) represents\ (x_i \) is false)
Then there is for each side to \ ((A, b) \) , we give it this sense: if \ (a \) should be satisfied, the \ (b \) must also be satisfied
In this way, we can use the following method determine whether the solution:
- Where solvability: \ (\ FORALL \ I \ in n-\) , \ (I \) and \ (i + n \) does not belong to the same strongly connected component.
- Where no solution: \ (\ EXISTS \ I \ in n-\) , \ (I \) and \ (i + n \) belong to the same strongly connected component.
Because, according to the construction side of our method above, belonging to two points with a proposition strongly connected components they represent are to be simultaneously true.
And because the same Boolean variable \ (x \) will not have two values simultaneously, more than determine the correctness of the method is obvious.
FIG then we just completed, run again \ (\ text {Tarjan} \ ) then may judge as described above.
So, the next step is the most important: how to build map?
In fact, this is not difficult, as long as the abstract \ (\ {x_n \} \ ) and \ (m \) propositions like, to this question, for example, to deepen understanding about.
The basic idea
We \ (n-\) comp ingredients abstracted \ (\ {x_n \} \) , the first \ (I \) represents a sample made of ingredients of Han \ (x_i \) is true (point \ (I \) ), Conversely represents \ (x_i \) is false (point \ (n-I + \) )
and demand for each review, similarly according to the above method of abstraction at
two propositions is then given for each requirement \ (the p-, q \) , we do not even two sides \ ((\ lnot p, q ) \) and \ ((\ lnot q, the p-) \)
(As for where \ (p \) and \ (q \) What it is possible to think about themselves)
Details Notes
- Since our \ (n \) kind of food will be split into two points, so points to open space twice.
- Since our \ (m \) entry requirements will have two sides, so the edge of space have opened twice.
- Each time the initialization, if the \ (\ text {for} \ ) cycle empty array, must pay attention to the upper bound enumerated (see above two).
Reference Code
Maybe I write not very good, do not understand, then you can combine my understanding of the codeTo praise it ah ah ah
/*--------------------------------
Code name: meal.cpp
Author: The Ace Bee
This code is made by The Ace Bee
--------------------------------*/
#include <cstdio>
#include <cstring>
#define rg register
#define fileopen(x) \
freopen(x".in", "r", stdin); \
freopen(x".out", "w", stdout);
#define fileclose \
fclose(stdin); \
fclose(stdout);
const int MAXN = 233;
const int MAXM = 2333;
inline int min(int a, int b) { return a < b ? a : b; }
inline int read() {
int s = 0; bool f = false; char c = getchar();
while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
return f ? -s : s;
}
int tot, head[MAXN], nxt[MAXM], ver[MAXM];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }
int n, num, dfn[MAXN], low[MAXN];
int st[MAXN], top, co[MAXN], col;
inline void tarjan(int u) {
dfn[u] = low[u] = ++num, st[++top] = u;
for (rg int v, i = head[u]; i; i = nxt[i]) {
if (!dfn[v = ver[i]])
tarjan(v), low[u] = min(low[u], low[v]);
else
if (!co[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
++col;
do co[st[top]] = col, --top;
while (st[top + 1] != u);
}
}
inline void init() {
tot = col = num = top = 0;
memset(co, 0, sizeof co);
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(head, 0, sizeof head);
}
int main() {
// fileopen("meal");
char sa[10], sb[10];
for (rg int T = read(); T; --T) {
init();
int n = read();
for (rg int m = read(); m; --m) {
scanf("%s%s", sa, sb);
int a = 0, lena = strlen(sa);
for (rg int i = 1; i < lena; ++i)
a = (a << 3) + (a << 1) + (sa[i] ^ 48);
int b = 0, lenb = strlen(sb);
for (rg int i = 1; i < lenb; ++i)
b = (b << 3) + (b << 1) + (sb[i] ^ 48);
if (sa[0] == 'h' && sb[0] == 'h')
Add_edge(a + n, b), Add_edge(b + n, a);
else if (sa[0] == 'h' && sb[0] == 'm')
Add_edge(a + n, b + n), Add_edge(b, a);
else if (sa[0] == 'm' && sb[0] == 'h')
Add_edge(a, b), Add_edge(b + n, a + n);
else if (sa[0] == 'm' && sb[0] == 'm')
Add_edge(a, b + n), Add_edge(b, a + n);
}
for (rg int i = 1; i <= n << 1; ++i)
if (!dfn[i]) tarjan(i);
int flag = 1;
for (rg int i = 1; i <= n; ++i)
if (co[i] == co[i + n]) { flag = 0; break; }
puts(flag ? "GOOD" : "BAD");
}
// fileclose;
return 0;
}
End Sahua \ (qwq \)