Pagini recente » Cod sursa (job #232855) | Cod sursa (job #2768616) | Cod sursa (job #3197293) | Cod sursa (job #2920581) | Cod sursa (job #3227375)
// 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 Imply(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.Imply(-a, b);
} else if (type == 1) {
graph.Imply(-a, -b);
} else if (type == 2) {
graph.Imply(-b, -a);
} else if (type == 3) {
graph.Imply(a, -b);
}
}
auto res = Solve(graph);
cout << res.size() << "\n";
for (const auto& node : res) {
cout << node << "\n";
}
return 0;
}