1
1
import sys
2
2
from collections import deque
3
3
4
+ # This problem can be reduced to a 2-SAT problem
5
+ # 2-SAT problem can be then solved efficiently by using an implication graph
6
+ # It's solved 3 different ways:
7
+ # ... 1- Naive solution
8
+ # ... 2- Implication graph + recursive DFS
9
+ # ... 3- Implication graph + Iterative DFS
10
+
4
11
class Implication_graph :
5
12
6
13
def __init__ (self , n , clauses ):
@@ -109,14 +116,14 @@ def dfs(self, an_adjacency_list, dfs_preorder, dfs_postorder, iterative):
109
116
else :
110
117
self .explore (v , an_adjacency_list , dfs_preorder , dfs_postorder )
111
118
112
- def stronly_connected_components (self ):
119
+ def stronly_connected_components (self , iterative ):
113
120
114
121
dfs_postorder = []
115
122
116
123
# 1. Find postorder in Gr
117
124
# ... Source vertices in Gr have the highest postorder
118
125
# ... A source vertice in Gr is Sink vertice in G
119
- self .dfs (self .reversed_adjacency_list , None , dfs_postorder , iterative = True )
126
+ self .dfs (self .reversed_adjacency_list , None , dfs_postorder , iterative )
120
127
121
128
# 2. Find SCCs in G
122
129
sccs = []
@@ -125,13 +132,16 @@ def stronly_connected_components(self):
125
132
v = dfs_postorder [i ]
126
133
if not self .visited [v ]:
127
134
sccs .append ([])
128
- self .explore_iterative (v , self .adjacency_list , None , sccs [len (sccs ) - 1 ])
135
+ if iterative :
136
+ self .explore_iterative (v , self .adjacency_list , None , sccs [len (sccs ) - 1 ])
137
+ else :
138
+ self .explore (v , self .adjacency_list , None , sccs [len (sccs ) - 1 ])
129
139
130
140
return sccs
131
141
132
- def solve_2sat (self ):
142
+ def solve_2sat (self , iterative ):
133
143
134
- strongly_connected_components = self .stronly_connected_components ()
144
+ strongly_connected_components = self .stronly_connected_components (iterative )
135
145
136
146
# sccs is ordered in reversed topological order
137
147
vertice_assignment = [- 1 ] * self .vertices_count
@@ -159,11 +169,11 @@ def __init__(self, vertice, adjacent_index):
159
169
self .vertice = vertice
160
170
self .adjacent_index = adjacent_index
161
171
162
- def isSatisfiable (n , clauses ):
172
+ def isSatisfiable (n , clauses , iterative ):
163
173
164
174
g = Implication_graph (n , clauses )
165
175
166
- return g .solve_2sat ()
176
+ return g .solve_2sat (iterative )
167
177
168
178
# Naive Solution:
169
179
# Time Complexity: O(2^n)
@@ -190,9 +200,9 @@ def isSatisfiable_naive(n, clauses):
190
200
191
201
n , m = map (int , input ().split ())
192
202
clauses = [ list (map (int , input ().split ())) for i in range (m ) ]
193
-
203
+
194
204
#result = isSatisfiable_naive(n, clauses)
195
- result = isSatisfiable (n , clauses )
205
+ result = isSatisfiable (n , clauses , iterative = True )
196
206
197
207
if result is None :
198
208
print ("UNSATISFIABLE" )
0 commit comments