slash0t

2sat (not my)

Apr 7th, 2025
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.34 KB | None | 0 0
  1. struct two_sat {
  2.     int n;
  3.     vector<vector<int>> g, gr; // gr is the reversed graph
  4.     vector<int> comp, topological_order, answer; // comp[v]: ID of the SCC containing node v
  5.     vector<bool> vis;
  6.  
  7.     two_sat() {}
  8.  
  9.     two_sat(int _n) { init(_n); }
  10.  
  11.     void init(int _n) {
  12.         n = _n;
  13.         g.assign(2 * n, vector<int>());
  14.         gr.assign(2 * n, vector<int>());
  15.         comp.resize(2 * n);
  16.         vis.resize(2 * n);
  17.         answer.resize(2 * n);
  18.     }
  19.  
  20.     void add_edge(int u, int v) {
  21.         g[u].push_back(v);
  22.         gr[v].push_back(u);
  23.     }
  24.  
  25.     // For the following three functions
  26.     // int x, bool val: if 'val' is true, we take the variable to be x. Otherwise we take it to be x's complement.
  27.  
  28.     // At least one of them is true
  29.     void add_clause_or(int i, bool f, int j, bool g) {
  30.         add_edge(i + (f ? n : 0), j + (g ? 0 : n));
  31.         add_edge(j + (g ? n : 0), i + (f ? 0 : n));
  32.     }
  33.  
  34.     // Only one of them is true
  35.     void add_clause_xor(int i, bool f, int j, bool g) {
  36.         add_clause_or(i, f, j, g);
  37.         add_clause_or(i, !f, j, !g);
  38.     }
  39.  
  40.     // Both of them have the same value
  41.     void add_clause_and(int i, bool f, int j, bool g) {
  42.         add_clause_xor(i, !f, j, g);
  43.     }
  44.  
  45.     // Topological sort
  46.     void dfs(int u) {
  47.         vis[u] = true;
  48.  
  49.         for (const auto &v : g[u])
  50.             if (!vis[v]) dfs(v);
  51.  
  52.         topological_order.push_back(u);
  53.     }
  54.  
  55.     // Extracting strongly connected components
  56.     void scc(int u, int id) {
  57.         vis[u] = true;
  58.         comp[u] = id;
  59.  
  60.         for (const auto &v : gr[u])
  61.             if (!vis[v]) scc(v, id);
  62.     }
  63.  
  64.     // Returns true if the given proposition is satisfiable and constructs a valid assignment
  65.     bool satisfiable() {
  66.         fill(vis.begin(), vis.end(), false);
  67.  
  68.         for (int i = 0; i < 2 * n; i++)
  69.             if (!vis[i]) dfs(i);
  70.  
  71.         fill(vis.begin(), vis.end(), false);
  72.         reverse(topological_order.begin(), topological_order.end());
  73.  
  74.         int id = 0;
  75.         for (const auto &v : topological_order)
  76.             if (!vis[v]) scc(v, id++);
  77.  
  78.         // Constructing the answer
  79.         for (int i = 0; i < n; i++) {
  80.             if (comp[i] == comp[i + n]) return false;
  81.             answer[i] = (comp[i] > comp[i + n] ? 1 : 0);
  82.         }
  83.  
  84.         return true;
  85.     }
  86. };
Add Comment
Please, Sign In to add comment