题意:有m个评委,每个评委有两个要求,只要满足某个要求即可通过审核。问是否有一种方案能够通过所有评委审核。
分析:把每个点分成x和x+n两个点。x表示汉式,x+n表示满式。设next(x)为x的另一种做法。若某个评委的要求为x、y则连边next(x)->y,next(y)->x。剩下的就是裸的2-SAT判定问题了。
代码:
var e,sum,tot,n,m,d:longint; stack,last,belong,low,dfn:array[1..500] of longint; f:array[1..500] of boolean; side:array[1..100000] of record x,y,next:longint; end; function next(x:longint):longint; begin if x>n then exit(x-n) else exit(x+n); end; procedure add(x,y:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].next:=last[x]; last[x]:=e; end; procedure init; var x,y,i:longint; c:char; begin e:=0; fillchar(last,sizeof(last),0); fillchar(dfn,sizeof(dfn),0); fillchar(low,sizeof(low),0); fillchar(f,sizeof(f),false); tot:=0; sum:=0; d:=0; readln(n,m); for i:=1 to m do begin read(c); read(x); if c='m' then x:=x+n; read(c); read(c); readln(y); if c='m' then y:=y+n; add(next(x),y); add(next(y),x); end; end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure dfs(x:longint); var i:longint; begin inc(d); dfn[x]:=d; low[x]:=d; inc(tot); stack[tot]:=x; f[x]:=true; i:=last[x]; while i>0 do with side[i] do begin if dfn[y]=0 then begin dfs(y); low[x]:=min(low[x],low[y]); end else if f[y] then low[x]:=min(low[x],dfn[y]); i:=next; end; if dfn[x]=low[x] then begin inc(sum); repeat i:=stack[tot]; dec(tot); f[i]:=false; belong[i]:=sum; until i=x; end; end; procedure tarjan; var i:longint; begin for i:=1 to n*2 do if dfn[i]=0 then dfs(i); end; procedure print; var i:longint; flag:boolean; begin flag:=true; for i:=1 to n do if belong[i]=belong[i+n] then begin flag:=false; break; end; if flag then writeln('GOOD') else writeln('BAD'); end; procedure main; var t,l:longint; begin readln(t); for l:=1 to t do begin init; tarjan; print; end; end; begin main; end.