Cod sursa(job #3229547)

Utilizator AlexZeuVasile Alexandru AlexZeu Data 16 mai 2024 16:43:49
Problema 2SAT Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.43 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <random>
#include <unordered_map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#define ll long long
#define nl '\n'
#define FOR(i, a, b) for (int i = a; i <= b; ++i) 
#define F0R(i, a, b) for (int i = a; i >= b; --i)
#define FORd(i, n) for (int i = 0; i < n; ++i)
#define F0Rd(i, n) for (int i = n - 1; i >= 0; --i)
#define trav(a, x) for (auto &a : x)
#define uid(a, b) uniform_int_distribution<int>(a, b)(rng)

int not_x(int x, int n) {
    if (x <= n) {
        return n + x;
    }
    return x - n;
}

const int mxN = 2e5 + 5;

int timestamp, curr_component;
std::bitset<mxN> in_stack;
std::bitset<mxN> visited;
std::stack<int> visiting;
int found[mxN], low_link[mxN];

void dfs(int node, std::vector<int> graph[], std::vector<int> components[], std::unordered_map<int, int> &components_mapping) {
    found[node] = low_link[node] = ++timestamp;
    visiting.push(node);
    in_stack[node] = 1;
    visited[node] = 1;

    for (int x : graph[node]) {
        if (!visited[x]) {
            dfs(x, graph, components, components_mapping);
            low_link[node] = std::min(low_link[node], low_link[x]);
        } else if (in_stack[x]) {
            low_link[node] = std::min(low_link[node], found[x]);
        }
    }

    if (found[node] == low_link[node]) {
        while (true) {
            int x = visiting.top();
            visiting.pop();
            in_stack[x] = 0;
            components[curr_component].push_back(x);
            components_mapping[x] = curr_component;

            if (x == node) break;
        }

        curr_component++;
    }
}

void build_components(std::vector<int> graph[], std::vector<int> components[], std::unordered_map<int, int> &components_mapping, int nodes) {
    /* Use tarjan algorithm. */
    for (int i = 0; i < nodes; ++i) {
        if (!visited[i]) {
            dfs(i, graph, components, components_mapping);
        }
    }
}

std::vector<int> topological_sort(std::vector<int> graph[], int nodes) {
    /* Use kahn algorithm. */
    std::vector<int> order;
    std::vector<int> in_degree(nodes, 0);
    std::queue<int> q;

    for (int i = 0; i < nodes; ++i) {
        for (int x : graph[i]) {
            in_degree[x]++;
        }
    }

    for (int i = 0; i < nodes; ++i) {
        if (in_degree[i] == 0) {
            q.push(i);
        }
    }

    while (!q.empty()) {
        int node = q.front();
        q.pop();
        order.push_back(node);

        for (int x : graph[node]) {
            in_degree[x]--;
            if (in_degree[x] == 0) {
                q.push(x);
            }
        }
    }

    return order;
}

int main() {
    int n, m;

    std::ifstream fin("2sat.in");
    std::ofstream fout("2sat.out");

    fin >> n >> m; 

    std::vector<int> edges[2 * n + 1];
    std::vector<std::pair<int, int>> all_edges;

    while (m--) {
        int x, y;
        fin >> x >> y;
        if (x < 0) x = n - x;
        if (y < 0) y = n - y;
        edges[not_x(x, n)].push_back(y);
        edges[not_x(y, n)].push_back(x);
        all_edges.push_back({not_x(x, n), y});
        all_edges.push_back({not_x(y, n), x});
    }

    std::unordered_map<int, int> components_mapping;
    std::vector<int> components[2 * n + 1];
    build_components(edges, components, components_mapping, 2 * n + 1);

    /* Check if formula is satisfiable. */
    for (int i = 1; i <= n; ++i) {
        if (components_mapping[i] == components_mapping[i + n]) {
            fout << -1 << nl;
            return 0;
        }
    }

    std::vector<int> compressed_graph[2 * n + 1];
    std::set<std::pair<int, int>> used_compressed_edges;

    for (auto &[x, y] : all_edges) {
        int cx = components_mapping[x], cy = components_mapping[y];

        if (cx == cy) continue;
        if (used_compressed_edges.find({cx, cy}) != used_compressed_edges.end()) continue;

        compressed_graph[cx].push_back(cy);
        used_compressed_edges.insert({cx, cy});
    }

    std::vector<int> order = topological_sort(compressed_graph, 2 * n + 1);
    std::reverse(order.begin(), order.end());
    std::vector<int> result(2 * n + 1, -1);

    for (int i = 0; i < order.size(); ++i) {
        int component = order[i];
        for (int x : components[component]) {
            if (result[x] == -1) {
                result[x] = 1;
                result[not_x(x, n)] = 0;
            }
        }
    }

    for (int i = 1; i <= n; ++i) {
        fout << result[i] << " ";
    }

    return 0;
}