2-SAT

O(n + m)

Satisfiability of clauses with two literals each, via the implication graph: clause (a or b) becomes edges ¬a→b and ¬b→a, then a variable and its negation must land in different SCCs. Needs the SCC (Kosaraju) template pasted above this; its topological component ids make the assignment rule a one-liner.

// use it on

CSES: Giant Pizza

Each family member gives a clause of two topping literals. Feasibility plus an assignment is exactly what solve() returns.

// the code

// requires the SCC (Kosaraju) template
struct TwoSat {
    int n;
    SCC scc;
    TwoSat(int n) : n(n), scc(2 * n) {}  // literal x -> node 2x, !x -> 2x+1
    // add clause (a or b); pass (var, isPositive) for each literal
    void add_clause(int a, bool va, int b, bool vb) {
        scc.add_edge(2 * a + (va ? 1 : 0), 2 * b + (vb ? 0 : 1));  // !a -> b
        scc.add_edge(2 * b + (vb ? 1 : 0), 2 * a + (va ? 0 : 1));  // !b -> a
    }
    // returns an assignment, or {} if unsatisfiable
    vector<bool> solve() {
        scc.run();
        vector<bool> res(n);
        for (int x = 0; x < n; x++) {
            if (scc.comp[2 * x] == scc.comp[2 * x + 1]) return {};
            res[x] = scc.comp[2 * x] > scc.comp[2 * x + 1];
        }
        return res;
    }
};

// more dags & satisfiability