#!/usr/bin/env python3
import sys,lzma,random,time
def read(path):
 op=lzma.open if path.endswith('.xz') else open; n=0; pos=[]; neg=[]
 with op(path,'rt') as f:
  for line in f:
   if not line or line[0] in 'c%0': continue
   if line[0]=='p': n=int(line.split()[2]); continue
   lits=[int(x) for x in line.split() if x!='0']
   if all(x>0 for x in lits): pos.append([abs(x) for x in lits])
   elif all(x<0 for x in lits): neg.append([abs(x) for x in lits])
   else: return n,None,None
 return n,pos,neg
def ok(n,pos,neg,S):
 for c in pos:
  if all(v in S for v in c): return False
 for c in neg:
  if not any(v in S for v in c): return False
 return True
def solve(n,pos,neg,secs):
 rng=random.Random(2); end=time.time()+secs
 forbid=[[] for _ in range(n+1)]
 for c in pos:
  for v in c: forbid[v].append(c)
 # incidence long uncovered
 inc=[[] for _ in range(n+1)]
 for i,c in enumerate(neg):
  for v in c: inc[v].append(i)
 best=10**9
 while time.time()<end:
  S=set(); hit=[0]*len(neg); uncovered=set(range(len(neg)))
  # weighted greedy hitting: repeatedly cover hardest uncovered long clause
  while uncovered and time.time()<end:
   ci=min(random.sample(tuple(uncovered), min(len(uncovered),20)), key=lambda j: sum(1 for v in neg[j] if all(not all((u==v or u in S) for u in fc) for fc in forbid[v])))
   cand=[]
   for v in neg[ci]:
    if v in S: continue
    if any(all((u==v or u in S) for u in fc) for fc in forbid[v]): continue
    gain=sum(1 for j in inc[v] if hit[j]==0)
    cand.append((gain+rng.random()*3, v))
   if not cand: break
   _,v=max(cand); S.add(v)
   for j in inc[v]:
    if hit[j]==0: uncovered.discard(j)
    hit[j]+=1
  bad=sum(1 for c in neg if not any(v in S for v in c))
  if bad<best: best=bad
  if ok(n,pos,neg,S): return S,best
 return None,best
if __name__=='__main__':
 n,pos,neg=read(sys.argv[1]); sol,best=solve(n,pos,neg,float(sys.argv[2]) if len(sys.argv)>2 else 5)
 print('n',n,'pos',len(pos),'neg',len(neg),'sol',sol is not None,'size',len(sol or []),'best_unhit',best)
