Cod sursa(job #2462923)

Utilizator preda.andreiPreda Andrei preda.andrei Data 28 septembrie 2019 00:43:47
Problema 2SAT Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.3 kb
#include <fstream>
#include <stack>
#include <vector>

using namespace std;

struct Node
{
    vector<int> edges;
    int low = -1;
    int time = -1;
    int comp = -1;
    bool in_stack = false;
};

struct Graph
{
    vector<Node> nodes;
    int terms;

    Graph(int terms) : nodes(2 * terms + 3), terms(terms) {}

    void AddClause(int logical1, int logical2);

    int GetIndex(int logical) const;
    int GetLogical(int index) const;
};

void Graph::AddClause(int logical1, int logical2)
{
    int index1 = GetIndex(logical1);
    int index2 = GetIndex(logical2);

    int index_not1 = GetIndex(-logical1);
    int index_not2 = GetIndex(-logical2);

    nodes[index_not1].edges.push_back(index2);
    nodes[index_not2].edges.push_back(index1);
}

int Graph::GetIndex(int logical) const
{
    if (logical > 0) {
        return logical;
    }
    return terms - logical;
}

int Graph::GetLogical(int index) const
{
    if (index <= terms) {
        return index;
    }
    return terms - index;
}

void ExtractComponent(Graph &g, int last_node, stack<int> &st, vector<int> &order)
{
    static int curr_comp = 0;
    curr_comp += 1;

    while (order.empty() || order.back() != last_node) {
        g.nodes[st.top()].comp = curr_comp;
        g.nodes[st.top()].in_stack = false;
        order.push_back(st.top());
        st.pop();
    }
}

void Tarjan(Graph &g, int node, stack<int> &st, vector<int> &order)
{
    static int time = 0;
    g.nodes[node].low = g.nodes[node].time = (time += 1);

    st.push(node);
    g.nodes[node].in_stack = true;

    for (const auto &next : g.nodes[node].edges) {
        if (g.nodes[next].time == -1) {
            Tarjan(g, next, st, order);
            g.nodes[node].low = min(g.nodes[node].low, g.nodes[next].low);
        }
        if (g.nodes[next].in_stack) {
            g.nodes[node].low = min(g.nodes[node].low, g.nodes[next].time);
        }
    }

    if (g.nodes[node].low >= g.nodes[node].time) {
        ExtractComponent(g, node, st, order);
    }
}

vector<int> FindOrder(Graph &g)
{
    vector<int> order;
    for (int i = 1; i <= 2 * g.terms; i += 1) {
        if (g.nodes[i].time == -1) {
            stack<int> st;
            Tarjan(g, i, st, order);
        }
    }
    return order;
}

vector<bool> TwoSat(Graph &g)
{
    auto order = FindOrder(g);
    vector<bool> res(g.terms, false);
    vector<bool> set(g.terms, false);

    for (int i = order.size() - 1; i >= 0; i -= 1) {
        auto index = order[i];
        auto index_not = g.GetIndex(-g.GetLogical(index));
        if (g.nodes[index].comp == g.nodes[index_not].comp) {
            return vector<bool>();
        }

        auto value = (g.GetLogical(index) > 0 ? false : true);
        auto res_index = abs(g.GetLogical(index)) - 1;

        if (!set[res_index]) {
            res[res_index] = value;
            set[res_index] = true;
        }
    }
    return res;
}

int main()
{
    ifstream fin("2sat.in");
    ofstream fout("2sat.out");

    int terms, clauses;
    fin >> terms >> clauses;

    Graph graph(terms);
    for (int i = 0; i < clauses; i += 1) {
        int a, b;
        fin >> a >> b;
        graph.AddClause(a, b);
    }

    auto res = TwoSat(graph);
    if (res.empty()) {
        fout << "-1\n";
        return 0;
    }

    for (const auto &b : res) {
        fout << (b ? 1 : 0) << " ";
    }
    fout << "\n";

    return 0;
}