Advertisement
kartikkukreja

2SAT in linear time

May 15th, 2013
467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.26 KB | None | 0 0
  1. #include <cstdio>
  2. #include <vector>
  3. #include <cstring>
  4. #include <map>
  5. #define MAXN 1000
  6. #define SIZE (2*MAXN + 1)
  7. using namespace std;
  8.  
  9. typedef vector <int> vi;
  10.  
  11. // Assuming vertices are labeled 1...V
  12. vi G[SIZE], Grev[SIZE];
  13. bool explored[SIZE];
  14. int leader[SIZE], finish[SIZE], order[SIZE], t = 0, parent = 0;
  15. map <int, bool> truthAssignment;
  16.  
  17. // running DFS on the reverse graph
  18. void dfs_reverse(int i) {
  19.     explored[i] = true;
  20.     for(vi::iterator it = Grev[i].begin(); it != Grev[i].end(); it++)
  21.         if(!explored[*it])
  22.             dfs_reverse(*it);
  23.     t++;
  24.     finish[i] = t;
  25. }
  26.  
  27. // running DFS on the actual graph
  28. void dfs(int i) {
  29.     explored[i] = true;
  30.     leader[i] = parent;
  31.     for(vi::iterator it = G[i].begin(); it != G[i].end(); it++)
  32.         if(!explored[*it])
  33.             dfs(*it);
  34. }
  35.  
  36. // check if u & v are in the same connected component
  37. bool stronglyConnected(int u, int v)    {
  38.     return leader[u] == leader[v];
  39. }
  40.  
  41. int main()  {
  42.     int i, u, v, N, M;
  43.     // N is the number of variables and M is the number of clauses
  44.  
  45.     //freopen("input1.txt", "r", stdin);
  46.  
  47.     scanf("%d %d", &N, &M);
  48.     for(i=0; i<M; i++)  {
  49.         scanf("%d %d", &u, &v); /*  Each clause is of the form u or v
  50.                                     1 <= x <= N for an uncomplemented variable x
  51.                                     -N <= x <= -1 for a complemented variable x
  52.                                     -x is the complement of a variable x
  53.                                 */
  54.  
  55.     // Internally, complement of variable x is represented as N + x.
  56.         if(u > 0)   {
  57.             if(v > 0)   {
  58.                 G[N+u].push_back(v); G[N+v].push_back(u);
  59.                 Grev[v].push_back(N+u); Grev[u].push_back(N+v);
  60.             } else  {
  61.                 G[N+u].push_back(N-v); G[-v].push_back(u);
  62.                 Grev[N-v].push_back(N+u); Grev[u].push_back(-v);
  63.             }
  64.         } else  {
  65.             if(v > 0)   {
  66.                 G[-u].push_back(v); G[N+v].push_back(N-u);
  67.                 Grev[v].push_back(-u); Grev[N-u].push_back(N+v);
  68.             } else  {
  69.                 G[-u].push_back(N-v); G[-v].push_back(N-u);
  70.                 Grev[N-v].push_back(-u); Grev[N-u].push_back(-v);
  71.             }
  72.         }
  73.     }
  74.  
  75.     // run dfs on the reverse graph to get reverse postorder
  76.     memset(explored, false, (2*N + 1)*sizeof(bool));
  77.     for(i=2*N; i>0; i--)  {
  78.         if(!explored[i])
  79.             dfs_reverse(i);
  80.         order[finish[i]] = i;
  81.     }
  82.  
  83.     // run dfs on the actual graph in reverse postorder
  84.     memset(explored, false, (2*N + 1)*sizeof(bool));
  85.     for(i=2*N; i>0; i--)
  86.         if(!explored[order[i]]) {
  87.             parent = order[i];
  88.             dfs(order[i]);
  89.         }
  90. /*
  91.     printf("Original graph :\n");
  92.     for(i=1; i<=2*N; i++)  {
  93.         if(!G[i].empty())   {
  94.             printf("%d : ", i);
  95.             for(vi::iterator it = G[i].begin(); it != G[i].end(); it++)
  96.                 printf("%d ", *it);
  97.             printf("\n");
  98.         }
  99.     }
  100.  
  101.     printf("Reverse graph :\n");
  102.     for(i=1; i<=2*N; i++)  {
  103.         if(!Grev[i].empty())   {
  104.             printf("%d : ", i);
  105.             for(vi::iterator it = Grev[i].begin(); it != Grev[i].end(); it++)
  106.                 printf("%d ", *it);
  107.             printf("\n");
  108.         }
  109.     }
  110. */
  111.     // check if a variable and its complement belong in the same SCC in reverse postorder
  112.     // and assign truth values to SCC
  113.     for(i=2*N; i>0; i--)   {
  114.         u = order[i];
  115.         if(u > N)   {
  116.             if(stronglyConnected(u, u-N)) break;
  117.             if(truthAssignment.find(leader[u]) == truthAssignment.end())    {
  118.                 truthAssignment[leader[u]] = true;
  119.                 truthAssignment[leader[u-N]] = false;
  120.             }
  121.         } else {
  122.             if(stronglyConnected(u, N+u)) break;
  123.             if(truthAssignment.find(leader[u]) == truthAssignment.end())    {
  124.                 truthAssignment[leader[u]] = true;
  125.                 truthAssignment[leader[N+u]] = false;
  126.             }
  127.         }
  128.     }
  129.  
  130.     if(i > 0)
  131.         printf("Unsatisfiable\n");
  132.     else    {
  133.         printf("Satisfying assignment :\n");
  134.         for(i=1; i<=N; i++)
  135.             printf("%d : %s\n", i, truthAssignment[leader[i]] ? "true" : "false");
  136.     }
  137.  
  138.     return 0;
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement