CF228E-The Road to Berland is Paved With Good Intentions
题目大意
一张 \(n\) 个节点, \(m\) 条边的无向图,初始这些边有 \(0,1\) 边权。你可以进行操作是,选择一个节点,将所有连接该节点的边权取反。判断你是否可以通过 \(n\) 次以内操作,将所有边全部变成 \(1\) 。
题解
可以发现一个点连续取两次及以上是没有意义的。所以问题转化为每个点要不要取的问题。对于每条边,如果初始边权为 \(1\) ,那么两端的点要么都取,要么都不取才可以。如果初始边权为 \(0\) ,那么一边取一边不取才行。所以问题由此转化成了一个 \(2SAT\) 问题。
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define umap unordered_map
#define pq(x) priority_queue<x>
#define ppq(x) priority_queue<x,vector<x>,greater<x>>
#define endl '\n'
using namespace std;
using i128 = __int128;
const int mod =1e9+7;
template <typename T>void read(T&x){x=0;int f = 1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);x*=f;
}
template <typename T>void print(T x) {if (x < 0) { putchar('-'); x = -x; }if (x > 9) print(x / 10);putchar(x % 10 + '0');
}
#define int long long
class TwoSAT {
public:int n; int total_nodes; vector<vector<int>> adj; vector<int> dfs_num; vector<int> dfs_low; vector<bool> in_stack; stack<int> stk; vector<int> comp; int dfs_counter; int comp_cnt; vector<bool> assignment; void tarjan(int u) {dfs_num[u] = dfs_low[u] = ++dfs_counter;stk.push(u);in_stack[u] = true;for (int v : adj[u]) {if (dfs_num[v] == 0) {tarjan(v);dfs_low[u] = min(dfs_low[u], dfs_low[v]);} else if (in_stack[v]) {dfs_low[u] = min(dfs_low[u], dfs_num[v]);}}if (dfs_low[u] == dfs_num[u]) {int v;do {v = stk.top();stk.pop();in_stack[v] = false;comp[v] = comp_cnt;} while (v != u);comp_cnt++;}}int node(int x) const {return x > 0 ? 2 * (x - 1) : 2 * (-x - 1) + 1;}TwoSAT(int n) : n(n), total_nodes(2 * n) {adj.resize(total_nodes);dfs_num.resize(total_nodes, 0);dfs_low.resize(total_nodes, 0);in_stack.resize(total_nodes, false);comp.resize(total_nodes, -1);assignment.resize(n, false);dfs_counter = 0;comp_cnt = 0;}void add(int a, int b) {int a_node = node(a);int b_node = node(b);adj[a_node].push_back(b_node);adj[b_node].push_back(a_node);}bool solve() {for (int i = 0; i < total_nodes; i++) {if (dfs_num[i] == 0) {tarjan(i);}}for (int i = 0; i < total_nodes; i += 2) {if (comp[i] == comp[i ^ 1]) {return false; }}for (int i = 0; i < total_nodes; i += 2) {assignment[i / 2+1] = comp[i] < comp[i ^ 1];}return true;}
};
const int N=5e5+5;
const int M=2e6+5;
inline void solve()
{int n,m;cin>>n>>m;TwoSAT t(n);for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;if(w) t.add(u,v),t.add(-u,-v);else t.add(-u,v),t.add(u,-v);}if(!t.solve()){cout<<"Impossible"<<endl;}else{vector<int> ans;for(int i=1;i<=n;i++){if(t.assignment[i]) ans.push_back(i);}cout<<ans.size()<<endl;for(auto i:ans) cout<<i<<" ";}
// for(int i=0;i<2*n;i++) cout<<t.comp[i]<<" ";
}signed main()
{ios;int T=1;
// cin>>T;for(;T--;) solve();return 0;
}