Cod sursa(job #2848960)

Utilizator smoc_georgemarianSmoc George-Marian smoc_georgemarian Data 14 februarie 2022 12:25:20
Problema 2SAT Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.34 kb
#include <bits/stdc++.h>
using namespace std;

int realIndex(int x, int n)
{
    if ( x < 0 )
        return -x + n;
    return x;
}
void printValues(vector<vector<int>>&g, int n)
{
    int i;
    cout << "Values: \n";
    for (i = 1; i <= 2 * n; i++)
        {
        for (auto it : g[i])
            cout << it << " ";
        cout << "\n";
        }
}
void computeRelation(vector<vector<int>>& g, vector<vector<int>>& gt, int x, int y, int n)
{
    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, vector<int>&used, vector<vector<int>>&g, vector<int>&order)
{
    used[node] = true;
    for (int ngb: g[node])
    {
        if (!used[ngb])
            dfs(ngb, used, g, order);
        
    }
    order.push_back(node);
}
void dfs_2(int node, vector<int>&used, vector<vector<int>>&g, vector<int>&act_comp)
{
    used[node] = true;
    act_comp.push_back(node);
    for (auto ngb: g[node])
    {
        if (!used[ngb])
            dfs_2(ngb, used, g, act_comp);
    }
}
void computeTarjan(vector<vector<int>>&g, vector<vector<int>>&gt, vector<vector<int>>& comps, int n, vector<int>& contracted_node)
{
    vector<int> used(2 * n + 1), order;
    vector<int> act_comp;
    for (int i = 1; i <= 2 * n; ++i)
        if (!used[i])
            dfs(i, used, g, order);
    fill(used.begin(), used.end(), 0);
    for (auto it = order.rbegin(); it != order.rend(); ++it)
        if (!used[*it])
        {
            act_comp.clear();
            dfs_2(*it, used, gt, act_comp);
            // merge nodes
            for (auto it : act_comp)
                contracted_node[it] = comps.size();
            comps.push_back(act_comp);
        }
}
bool checkIfPossible(vector<int>& contracted_node, int n)
{
    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(vector<vector<int>>&g, vector<int>&contracted_node, int n, vector<int>& dg,
    vector<vector<int>>& comps, vector<int>& value)
{
    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)
        cout << value[i] << " ";

}
int main()
{
    freopen("2sat.in", "r", stdin);
    freopen("2sat.out", "w", stdout);
    
    int n, m;
    cin >> n >> m;
    vector<vector<int>>g(2 * n + 1);
    vector<vector<int>>gt(2 * n + 1);
    vector<int> value(n + 1, -1);

    vector<vector<int>>comps;
    vector<int> contracted_node(2 * n + 1);
    vector<int> dg( 2 * n + 1);
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        computeRelation(g, gt, x, y, n);
    }
    // printValues(g, n);
    // printValues(gt, n);
    computeTarjan(g, gt, comps, n, contracted_node);
    bool verdict = checkIfPossible(contracted_node, n);
    if (!verdict)
        {cout << -1; return 0;}
    computeAssignment(g, contracted_node, n, dg, comps, value);
    return 0;
}