bzoj 1823: [JSOI2010]满汉全席 2-SAT判定

题意:有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.


你可能感兴趣的:(bzoj 1823: [JSOI2010]满汉全席 2-SAT判定)