Cod sursa(job #2848993)

Utilizator smoc_georgemarianSmoc George-Marian smoc_georgemarian Data 14 februarie 2022 12:45:30
Problema 2SAT Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.79 kb
#include <bits/stdc++.h>
using namespace std;
const int NMAX = (1e5 + 3);
int n, m;

vector<vector<int>>g(2 * NMAX + 1);
vector<vector<int>>gt(2 * NMAX + 1);
vector<int> value(NMAX + 1, -1);

vector<vector<int>>comps;
vector<int> contracted_node(2 * NMAX + 1);
vector<int> dg( 2 * NMAX + 1);
vector<int> used ( 2 * NMAX + 1);
vector<int> order;
int realIndex(int x, int n)
{
    if ( x < 0 )
        return -x + n;
    return x;
}

void printValues(vector<vector<int>>&g)
{
    int i;
    cout << "Values: \n";
    for (i = 1; i <= 2 * n; i++)
        {
        for (auto it : g[i])
            cout << it << " ";
        cout << "\n";
        }
}
void computeRelation(int x, int y)
{
    int real_x = realIndex(x, n);
    int real_y = realIndex(y, n);
    int real_non_x = realIndex(-x, n);
    int real_non_y = realIndex(-y, n);

    g[real_non_x].push_back(real_y);
    gt[real_y].push_back(real_non_x);

    g[real_non_y].push_back(real_x);
    gt[real_x].push_back(real_non_y);
}
void dfs(int node)
{
    used[node] = true;
    for (int ngb: g[node])
    {
        if (!used[ngb])
            dfs(ngb);
        
    }
    order.push_back(node);
}
void dfs_2(int node, vector<int>&act_comp)
{
    used[node] = true;
    act_comp.push_back(node);
    for (auto ngb: gt[node])
    {
        if (!used[ngb])
            dfs_2(ngb, act_comp);
    }
}
void computeKosaraju()
{
    for (int i = 1; i <= 2 * n; ++i)
        if (!used[i])
            dfs(i);
    fill(used.begin(), used.end(), 0);
    for (auto it = order.rbegin(); it != order.rend(); ++it)
        if (!used[*it])
        {
            vector<int> act_comp; 
            dfs_2(*it, act_comp);
            // merge nodes
            for (auto it : act_comp)
                contracted_node[it] = comps.size();
            comps.push_back(act_comp);
        }
}
bool checkIfPossible()
{
    for (int i = 1; i <= n; i++)
        {
        int cnode_i = contracted_node[i];
        int cnode_n = contracted_node[i + n];
        if (contracted_node[i] == contracted_node[i + n])
            return 0;
        }
    return 1;
}
void computeAssignment()
{
    for (int node = 1; node <= 2 * n; node++)
    {
        for (auto ngb: g[node])
            if (contracted_node[node] != contracted_node[ngb])
                dg[contracted_node[ngb]]++;

    }
    queue<int>Q;
    for (int i = 0; i < comps.size(); i++)
    {
        if (!dg[i])
            Q.push(i);
    }
    while(!Q.empty())
    {
        int act = Q.front();
        Q.pop();
        for (auto node : comps[act])
        {
            int realVar = (node > n) ? node - n : node;
            if (value[realVar] == -1)
                value[realVar] = (node <= n) ? 0 : 1;
        }
        // decrease dg for adjacent components
        for (auto node : comps[act])
        {
            for (auto ngb : g[node])
            {
                int cnode_node = contracted_node[node];
                int cnode_ngb = contracted_node[ngb];
                if (cnode_node != cnode_ngb)
                    {
                        dg[cnode_ngb]--;
                        if (!dg[cnode_ngb])
                            Q.push(cnode_ngb);
                    }
            }
        }
    }
    for (int i = 1; i <= n; ++i)
        printf("%d ", value[i]);

}
int main()
{
    freopen("2sat.in", "r", stdin);
    freopen("2sat.out", "w", stdout);
    
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        computeRelation(x, y);
    }
    // printValues(g);
    // printValues(gt);
    computeKosaraju();
    bool verdict = checkIfPossible();
    if (!verdict)
        {cout << -1; return 0;}
    computeAssignment();
    return 0;
}