CF228E-The Road to Berland is Paved With Good Intentions

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;
}


posted @ 2025-12-04 13:19  NDAKJin  阅读(8)  评论(0)    收藏  举报