luoguP4171 [JSOI2010] Feast

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 \)

Guess you like

Origin www.cnblogs.com/zsbzsb/p/11261844.html