Cod sursa(job #2787062)

Utilizator preda.andreiPreda Andrei preda.andrei Data 22 octombrie 2021 13:15:46
Problema 2SAT Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.29 kb
#include <algorithm>
#include <fstream>
#include <stack>
#include <unordered_map>
#include <vector>

using namespace std;

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

struct Graph {
    unordered_map<int, Node> nodes;

    Graph(int vars);

    int Size() const;

    void AddCond(int a, int b);

    Node& operator[](int index);
    const Node& operator[](int index) const;
};

Graph::Graph(int vars) {
    for (int i = 1; i <= vars; i += 1) {
        nodes[i] = Node{};
        nodes[-i] = Node{};
    }
}

int Graph::Size() const {
    return nodes.size();
}

void Graph::AddCond(int a, int b) {
    nodes[-a].edges.push_back(b);
    nodes[-b].edges.push_back(a);
}

Node& Graph::operator[](int index) {
    return nodes[index];
}

const Node& Graph::operator[](int index) const {
    return nodes.at(index);
}

void Extract(Graph& graph, int end_node, stack<int>& st, vector<int>& order) {
    static auto id = 0;
    id += 1;

    while (order.empty() || order.back() != end_node) {
        auto node = st.top();
        st.pop();
        graph[node].in_stack = false;
        graph[node].comp = id;
        order.push_back(node);
    }
}

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

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

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

    if (graph[node].low >= graph[node].time) {
        Extract(graph, node, st, order);
    }
}

vector<int> FindOrder(Graph& graph) {
    vector<int> order;
    order.reserve(graph.Size());

    for (int i = 1; i <= graph.Size() / 2; i += 1) {
        for (int sign = -1; sign <= 1; sign += 2) {
            auto node = sign * i;
            if (graph[node].time == -1) {
                stack<int> st;
                Dfs(graph, node, st, order);
            }
        }
    }
    reverse(order.begin(), order.end());
    return order;
}

vector<bool> Solve(Graph& graph) {
    unordered_map<int, bool> has_value;
    for (const auto& node : FindOrder(graph)) {
        if (graph[node].comp == graph[-node].comp) {
            return vector<bool>{};
        }
        if (!has_value[node]) {
            graph[node].value = false;
            graph[-node].value = true;
            has_value[node] = has_value[-node] = true;
        }
    }

    vector<bool> res(graph.Size() / 2);
    for (int i = 1; i <= graph.Size() / 2; i += 1) {
        res[i - 1] = graph[i].value;
    }
    return res;
}

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

    int vars, conds;
    fin >> vars >> conds;

    Graph graph(vars);
    for (int i = 0; i < conds; i += 1) {
        int a, b;
        fin >> a >> b;
        graph.AddCond(a, b);
    }

    auto res = Solve(graph);
    if (res.empty()) {
        fout << "-1\n";
    } else {
        for (const auto& value : res) {
            fout << (value ? 1 : 0) << " ";
        }
        fout << "\n";
    }
    return 0;
}