Cod sursa(job #3227374)

Utilizator preda.andreiPreda Andrei preda.andrei Data 29 aprilie 2024 23:26:09
Problema Party Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.3 kb
// TODO: Doc.

#include <algorithm>
#include <fstream>
#include <iostream>
#include <set>
#include <stack>
#include <vector>

using namespace std;

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

    bool has_value = false;
    bool value = false;
};

struct Graph {
    Graph(int vars) : nodes_(2 * vars) {
    }

    int Vars() const {
        return nodes_.size() / 2;
    }

    void AddCond(int a, int b) {
        nodes_[RealIndex(a)].edges.insert(b);
        nodes_[RealIndex(-b)].edges.insert(-a);
    }

    Node& operator[](int index) {
        return nodes_[RealIndex(index)];
    }

    const Node& operator[](int index) const {
        return nodes_[RealIndex(index)];
    }

 private:
    int RealIndex(int index) const {
        return index > 0 ? (index - 1) : (nodes_.size() + index);
    }

    vector<Node> nodes_;
};

void ExtractComp(
    Graph& graph, int end_node, stack<int>& st, vector<int>& order
) {
    while (order.empty() || order.back() != end_node) {
        auto node = st.top();
        st.pop();
        graph[node].in_stack = false;
        order.push_back(node);
    }
}

void Tarjan(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) {
            Tarjan(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) {
        ExtractComp(graph, node, st, order);
    }
}

vector<int> FindOrder(Graph& graph) {
    vector<int> order;
    for (int i = 1; i <= graph.Vars(); i += 1) {
        if (graph[i].time == -1) {
            stack<int> st;
            Tarjan(graph, i, st, order);
        }
        if (graph[-i].time == -1) {
            stack<int> st;
            Tarjan(graph, -i, st, order);
        }
    }
    reverse(order.begin(), order.end());
    return order;
}

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

    vector<int> res;
    for (int i = 1; i <= graph.Vars(); i += 1) {
        if (graph[i].value) {
            res.push_back(i);
        }
    }
    return res;
}

int main() {
    // #ifndef USE_STDIN
    ifstream cin("party.in");
    ofstream cout("party.out");
    // #endif

    int vars, conds;
    cin >> vars >> conds;

    Graph graph(vars);
    for (int i = 0; i < conds; i += 1) {
        int a, b, type;
        cin >> a >> b >> type;

        if (type == 0) {
            graph.AddCond(a, b);
        } else if (type == 1) {
            graph.AddCond(-a, -b);
        } else if (type == 2) {
            graph.AddCond(-b, -a);
        } else if (type == 3) {
            graph.AddCond(a, -b);
        }
    }

    auto res = Solve(graph);
    cout << res.size() << "\n";
    for (const auto& node : res) {
        cout << node << "\n";
    }
    return 0;
}