2-sat模板 hoj1917

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <stack>
#define DEBUG(x) cout << #x << " " << x << endl;
using namespace std;

 

class scc
{
private:
        const static int SIZE = 20000;
        const static int ESIZE = 20480 * 4;
        const static int RED = 1;
        const static int BLUE = 2;

        struct Edge
        {
                int v;
                Edge * nxt;
        } pool[ESIZE], *g[SIZE], *pp, *scc_g[SIZE];
        int indgr[SIZE], idx[SIZE], dfn[SIZE], low[SIZE];
        bool reach[SIZE], used[SIZE];
        int depth, cnt_scc;
        int n, m, zero_top, st_top, order;
        int st[SIZE], color[SIZE], sq[SIZE], pre[SIZE];

        void addedge(int a, int b, Edge *g[])
        {
                pp->v = b;
                pp->nxt = g[a];
                g[a] = pp++;
        }
        void dfs(int x);
        void toposort(int v);
        void becolor(int v);
public:
        void build_regraph();
        bool initialize();
        void output();
        bool solve();
};

void scc::build_regraph()
{
        memset(color, 0, sizeof (color));
        memset(scc_g, 0, sizeof (scc_g));
        memset(indgr, 0, sizeof (indgr));
        memset(pre, -1, sizeof (pre));
        for (int i = 0; i < n; i++)
        {
                if (pre[idx[i]] == -1)
                        pre[idx[i]] = i;
                for (Edge * ptr = g[i]; ptr != NULL; ptr = ptr->nxt)
                {
                        int w = ptr->v;
                        if (idx[i] != idx[w])
                        {
                                indgr[idx[i]]++;
                                addedge(idx[w], idx[i], scc_g);
                        }
                }
        }
}

bool scc::initialize()
{
        if (scanf("%d %d", &n, &m) != 2)
                return false;
        n *= 2;
        memset(g, 0, sizeof (g));
        memset(scc_g, 0, sizeof (scc_g));
        pp = pool;
        while (m--)
        {
                int a, b;
                scanf("%d %d", &a, &b);
                a--, b--;
                addedge(a, b ^ 1, g);
                addedge(b, a ^ 1, g);
        }
        zero_top = st_top = cnt_scc = depth = 0;
        memset(reach, false, sizeof (reach));
        memset(dfn, 0, sizeof (dfn));
        memset(low, 0, sizeof (low));
        return true;
}

void scc::dfs(int x)
{
        st[++st_top] = x;
        dfn[x] = low[x] = ++depth;
        int w;
        for (Edge * i = g[x]; i != NULL; i = i->nxt)
        {
                w = i->v;
                if (reach[w])
                        continue;
                else if (dfn[w] == 0)
                {
                        dfs(w);
                        low[x] = min(low[x], low[w]);
                }
                else
                        low[x] = min(low[x], dfn[w]);
        }
        if (low[x] == dfn[x])
        {
                cnt_scc++;
                do
                {
                        w = st[st_top--];
                        idx[w] = cnt_scc;
                        reach[w] = true;
                }
                while (w != x);
        }
}

bool scc::solve()
{
        for (int i = 0; i < n; i++)
                if (!reach[i])
                        dfs(i);
        for (int i = 0; i < n; i++)
                if (idx[i] == idx[i ^ 1])
                        return false;
        return true;
}

void scc::toposort(int v)
{
        used[v] = true;
        for (Edge *i = scc_g[v]; i != NULL; i = i->nxt)
        {
                if (!used[i->v])
                        toposort(i->v);
        }
        sq[order++] = v;
}

void scc::becolor(int v)
{
        color[v] = BLUE;
        for (Edge *i = scc_g[v]; i != NULL; i = i->nxt)
        {
                int w = i->v;
                if (!used[w])
                {
                        used[w] = true;
                        becolor(w);
                }
        }
}

void scc::output()
{
        order = 0;
        memset(used, 0, sizeof (used));
        for (int i = 1; i <= cnt_scc; i++)
        {
                if (!used[i])
                        toposort(i);
        }
        memset(used, 0, sizeof (used));
        reverse(sq,sq + order);
        for (int i = 0; i < order; i++)
        {
                if (!color[sq[i]])
                {
                        color[sq[i]] = RED;
                        int v = idx[pre[sq[i]] ^ 1];
                        if (color[v] == 0)
                                becolor(v);
                }
        }
        for (int i = 0; i < n; i += 2)
        {
                if (color[idx[i]] == RED)
                        printf("%d\n", i + 1);
                else if (color[idx[i ^ 1]] == RED)
                        printf("%d\n", (i ^ 1) + 1);
        }
}
scc g;

int main()
{
        while (g.initialize())
        {
                if (!g.solve())
                        printf("NIE\n");
                else
                {
                        g.build_regraph();
                        g.output();
                }
        }
        return 0;
}

你可能感兴趣的:(模板)