2-sat

时间很紧……没办法写总结……

切了poj6题和bzoj2题,总的来说这个东西不难,而且变形也不多。主要是要会建图,建图的话要找到每个东西的两种状态,然后再对限制条件建边。

推荐博客:http://blog.csdn.net/jarjingx/article/details/8521690(废话多但是里面总结的挺到位的,特别是建边四种模型,建议先看论文和课件再看这个博客)

然后也不多了……也就是最后答案是否要输出?如果不用就直接判断,如果用那是否需要字典序最小,如果不需要那就拓扑直接搞,如果需要就直接暴力染色判断(没写过但是白书里面有而且翻到两个大神的代码似乎还不错?:http://blog.csdn.net/u013532224/article/details/39739959;http://blog.163.com/shengrui_step/blog/static/20870918720141201262750/……)

更多的有时间再来吧……

就不吐槽最近的进度,而且小高一一来机房好吵!!!

2014.12.26------------------------------------------------------------------------------------

写一下求任意一组解的算法流程吧:

1)跑tarjan,然后看每个和他对立的点是否在一个scc中。如果是,那么此图无解。

2)如果点都满足1。那么缩点建图,不过边要建成与原来相反(link数组是为了防止某个scc有大量点连向另一个scc)

3)dfs。如果某个点还没被选中,那么就选他,然后把他的对立点的后继都弄成不选。

如果是字典序最小:

建完图后直接dfs。for一边每个店:如果某个点和他的对立点都没有被选中,先把这个点弄为选,跑dfs看是否矛盾,矛盾就把图复原一下再把这个点的对立点弄为选,跑dfs,如果还是不行就无解了……

-------------------------------------------------------------------------------------

按照大神博客推荐的顺序切

POJ - 3207 Ikki's Story IV - Panda's Trick

http://www.cnblogs.com/Macaulish/p/4181301.html

POJ - 3683 Priest John's Busiest Day

每对过密不是在第一个时间段结婚就是在第二个时间段结婚。

然后如果一对过密和另一对过密结婚世界重合了就连另一个时间段。

最后拓扑找方案

type
  arr=record
    toward,next:longint;
  end;

const
  maxn=20000;
  maxm=500000;

var
  edge:array[0..maxm]of arr;
  dfn,low,f1,f2,num,color,p,scc,a,b,c,link,rec:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  time,tot,sum,n,tail:longint;

function calc(ch:char):longint;
begin
  exit(ord(ch)-48);
end;

procedure add1(i,j:longint);
begin
  inc(tot);
  edge[tot].toward:=j;
  edge[tot].next:=f1[i];
  f1[i]:=tot;
end;

procedure add2(i,j:longint);
begin
  inc(tot);
  edge[tot].toward:=j;
  edge[tot].next:=f2[i];
  f2[i]:=tot;
  inc(num[j]);
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  chose[x]:=true;
  inc(tail);
  p[tail]:=x;
  i:=f1[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    repeat
      too:=p[tail];
      chose[too]:=false;
      scc[too]:=sum;
      dec(tail);
    until x=too;
  end;
end;

function ok:boolean;
var
  i:longint;
begin
  for i:=1 to n<<1 do
    if dfn[i]=0 then tarjan(i);
  for i:=1 to n do
    if scc[i]=scc[i+n] then exit(false);
  exit(true);
end;

procedure dfs(x:longint);
var
  i,too:longint;
begin
  color[x]:=2;
  i:=f2[x];
  while i>0 do begin
    too:=edge[i].toward;
    if color[too]=0 then dfs(too);
    i:=edge[i].next;
  end;
end;

function check(i,j,k,l:longint):boolean;
begin
  exit(not ((i>=l) or (k>=j)))
end;

procedure outo(x,y:longint);
begin
  if x<600 then write(0);
  write(x div 60,':');
  x:=x mod 60;
  if x<10 then write(0);
  write(x,' ');
  if y<600 then write(0);
  write(y div 60,':');
  y:=y mod 60;
  if y<10 then write(0);
  write(y);
  writeln;
end;

procedure into;
var
  i,j:longint;
  s:string;
begin
  readln(n);
  time:=0;
  sum:=0;
  for i:=1 to n do begin
    readln(s);
    while s[length(s)]=' ' do delete(s,length(s),1);
    a[i]:=calc(s[1])*600+calc(s[2])*60+calc(s[4])*10+calc(s[5]);
    delete(s,1,6);
    b[i]:=calc(s[1])*600+calc(s[2])*60+calc(s[4])*10+calc(s[5]);
    delete(s,1,6);
    val(s,c[i]);
  end;
  for i:=1 to n-1 do
    for j:=i+1 to n do begin
      if check(a[i],a[i]+c[i],a[j],a[j]+c[j]) then begin
        add1(i,j+n);
        add1(j,i+n);
      end;
      if check(a[i],a[i]+c[i],b[j]-c[j],b[j]) then begin
        add1(i,j);
        add1(j+n,i+n);
      end;
      if check(b[i]-c[i],b[i],a[j],a[j]+c[j]) then begin
        add1(i+n,j+n);
        add1(j,i);
      end;
      if check(b[i]-c[i],b[i],b[j]-c[j],b[j]) then begin
        add1(i+n,j);
        add1(j+n,i);
      end;
    end;
end;

procedure work;
var
  i,x,too,head,tail:longint;
begin
  if not ok then begin
    writeln('NO');
    exit;
  end;
  writeln('YES');
  for x:=1 to n<<1 do begin
    i:=f1[x];
    while i>0 do begin
      too:=edge[i].toward;
      if (scc[too]<>scc[n]) and (link[scc[too]]<>scc[n]) then begin
        link[scc[too]]:=scc[n];
        add2(scc[too],scc[n]);
      end;
      i:=edge[i].next;
    end;
  end;
  tail:=0;
  head:=1;
  for i:=1 to sum do
    if num[i]=0 then begin
      inc(tail);
      p[tail]:=i;
    end;
  while head<=tail do begin
    x:=p[head];
    inc(head);
    i:=f2[x];
    while i>0 do begin
      too:=edge[i].toward;
      dec(num[too]);
      if num[too]=0 then begin
        inc(tail);
        p[tail]:=too;
      end;
      i:=edge[i].next;
    end;
  end;
  for i:=1 to n do begin
    rec[scc[i]]:=scc[i+n];
    rec[scc[i+n]]:=scc[i];
  end;
  for i:=1 to sum do
    if color[p[i]]=0 then begin
      color[p[i]]:=1;
      dfs(rec[p[i]]);
    end;
  for i:=1 to n do
    if color[scc[i]]=1 then outo(a[i],a[i]+c[i])
      else outo(b[i]-c[i],b[i]);
end;


begin
  into;
  work;
end.
View Code

POJ - 3678 Katu Puzzle

这个题强烈建议自己写!!

各种情况的分类我也是醉了,写完后再也不担心不会建图了……

(找到某个建的比我的好比我的容易的大神的建法:

a and b ==1 , !a->a , !b -> b

a and b ==0 , a->!b , b->!a

a or b ==1 , !a->b , !b->a

a or b ==0 , a->!a , b->!b

a xor b ==1 , a->!b,!b->a,!a->b,b->!a

a xor b ==0 , a->b,b->a,!a->!b,!b->!a)

type
  arr=record
    toward,next:longint;
  end;

const
  maxn=3000;
  maxm=5000000;

var
  edge:array[0..maxm]of arr;
  chose:array[0..maxn]of boolean;
  dfn,low,first,p,scc:array[0..maxn]of longint;
  time,tot,n,m,tail,sum:longint;

procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  inc(tail);
  p[tail]:=x;
  chose[x]:=true;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    repeat
      too:=p[tail];
      dec(tail);
      chose[too]:=false;
      scc[too]:=sum;
    until x=too;
  end;
end;


procedure into;
var
  i,j,k,l:longint;
  ch:char;
begin
  readln(n,m);
  for i:=1 to m do begin
    read(j,k,l,ch);
    readln(ch);
    case ch of
      'A':if l=0 then begin
            add(j,k+n);
            add(k,j+n);
          end
          else begin
            add(j+n,j);
            add(k+n,k);
            add(j,k);
            add(k,j);
          end;
      'O':if l=0 then begin
            add(j,j+n);
            add(k,k+n);
            add(j+n,k+n);
            add(k+n,j+n);
          end
          else begin
            add(j+n,k);
            add(k+n,j);
          end;
      'X':if l=0 then begin
            add(j,k);
            add(k,j);
            add(j+n,k+n);
            add(k+n,j+n);
          end
          else begin
            add(j,k+n);
            add(k,j+n);

          end;
    end;
  end;
end;

procedure work;
var
  i:longint;
begin
  for i:=0 to n<<1-1 do
    if dfn[i]=0 then tarjan(i);
  for i:=0 to n-1 do
    if scc[i]=scc[i+n] then begin
      writeln('NO');
      exit;
    end;
  writeln('YES');
end;


begin
  into;
  work;
end.
View Code

POJ - 3648 Wedding

这题和上面某道类似,调了很久的原因是因为要输出的是和新娘坐在同一边而不是另一边(英语差所以题目看的hehe)

然后调试时自己被自己邪恶的内心搞笑到了(各种百合各种基……)

type
  arr=record
    toward,next:longint;
  end;

const
  maxm=1000000;
  maxn=90000;

var
  edge:array[0..maxm]of arr;
  color,num,first,rec,f2,dfn,low,scc,p,link:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  n,m,tot,time,sum,tail:longint;

procedure add1(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

procedure add2(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=f2[j];
  f2[j]:=tot;
  inc(num[k]);
end;

procedure dfs(x:longint);
var
  i,too:longint;
begin
  color[x]:=2;
  i:=f2[x];
  while i>0 do begin
    too:=edge[i].toward;
    if color[too]=0 then dfs(too);
    i:=edge[i].next;
  end;
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  chose[x]:=true;
  inc(tail);
  p[tail]:=x;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    num[sum]:=0;
    repeat
      too:=p[tail];
      dec(tail);
      scc[too]:=sum;
      chose[too]:=false;
    until x=too;
  end;
end;

procedure into;
var
  x1,x2,y1,y2,i,j:longint;
  s:string;
begin
  fillchar(dfn,sizeof(dfn),0);
  fillchar(low,sizeof(low),0);
  fillchar(first,sizeof(first),0);
  fillchar(f2,sizeof(f2),0);
  fillchar(color,sizeof(color),0);
  fillchar(link,sizeof(link),0);
  fillchar(chose,sizeof(chose),false);
  tot:=0;
  time:=0;
  tail:=0;
  sum:=0;
  for i:=1 to m do begin
    readln(s);
    s:=s+' ';
    j:=pos(' ',s);
    val(copy(s,1,j-2),x1);
    if s[j-1]='h' then begin
      x2:=x1;
      x1:=x1+n;
    end
    else x2:=x1+n;
    delete(s,1,j);
    j:=pos(' ',s);
    val(copy(s,1,j-2),y1);
    if s[j-1]='h' then begin
      y2:=y1;
      y1:=y1+n;
    end
    else y2:=y1+n;
    add1(x1,y2);
    add1(y1,x2);
  end;
  add1(0,0+n);
end;


procedure work;
var
  head,tail,o,j,x,too,i:longint;
begin
  for i:=0 to n<<1-1 do
    if dfn[i]=0 then tarjan(i);
  for i:=0 to n-1 do
    if scc[i]=scc[i+n] then begin
      writeln('bad luck');
      exit;
    end;
  for x:=0 to n<<1-1 do begin
    i:=first[x];
    while i>0 do begin
      too:=edge[i].toward;
      if (scc[too]<>scc[x]) and (link[scc[too]]<>scc[x]) then begin
        link[scc[too]]:=scc[x];
        add2(scc[too],scc[x]);
      end;
      i:=edge[i].next;
    end;
  end;
  head:=1;
  tail:=0;
  for i:=1 to sum do
    if num[i]=0 then begin
      inc(tail);
      p[tail]:=i;
    end;
  while head<=tail do begin
    x:=p[head];
    inc(head);
    i:=f2[x];
    while i>0 do begin
      too:=edge[i].toward;
      dec(num[too]);
      if num[too]=0 then begin
        inc(tail);
        p[tail]:=too;
      end;
      i:=edge[i].next;
    end;
  end;
  for i:=0 to n-1 do begin
    rec[scc[i]]:=scc[i+n];
    rec[scc[i+n]]:=scc[i];
  end;
  for i:=1 to sum do
    if color[p[i]]=0 then begin
      color[p[i]]:=1;
      dfs(rec[p[i]]);
    end;
  //j:=color[scc[0]];
  for i:=1 to n-1 do
    if color[scc[i]]=2 then
      write(i,'w ')
    else write(i,'h ');
  writeln;
end;

begin
  while true do begin
    readln(n,m);
    if n=0 then break;
    into;
    work;
  end;
end.
View Code

POJ - 2723 Get Luffy Out

这题要二分答案建图判断

一对钥匙不能同时取就是两个只能取一个

一个门一定要开就是两个都不能不取

然后二分答案建图去判断是否能到达某山门

type
  arr=record
    toward,next:longint;
  end;

const
  maxn=300000;
  maxm=600000;

var
  edge:array[0..maxm]of arr;
  dfn,low,first,scc,p,key1,key2,door1,door2:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  n,m,time,tot,sum,tail,nn:longint;

procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  inc(tail);
  p[tail]:=x;
  chose[x]:=true;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    repeat
      too:=p[tail];
      dec(tail);
      chose[too]:=false;
      scc[too]:=sum;
    until x=too;
  end;
end;

function check(x:longint):boolean;
var
  i:longint;
begin
  fillchar(dfn,sizeof(dfn),0);
  fillchar(low,sizeof(low),0);
  fillchar(first,sizeof(first),0);
  fillchar(chose,sizeof(chose),false);
  time:=0;
  tot:=0;
  tail:=0;
  sum:=0;
  for i:=1 to n do begin
    add(key1[i],key2[i]+nn);
    add(key2[i],key1[i]+nn);
  end;
  for i:=1 to x do begin
    add(door1[i]+nn,door2[i]);
    add(door2[i]+nn,door1[i]);
  end;
  for i:=0 to nn<<1-1 do
    if dfn[i]=0 then tarjan(i);
  for i:=0 to nn-1 do
    if scc[i]=scc[i+nn] then exit(false);
  exit(true)
end;

procedure work;
var
  i,left,right,ans,mid:longint;
begin
  nn:=n<<1;
  for i:=1 to n do readln(key1[i],key2[i]);
  for i:=1 to m do readln(door1[i],door2[i]);
  left:=0;
  right:=m+1;
  while left+1<right do begin
    mid:=(left+right)>>1;
    if check(mid)
      then left:=mid
      else right:=mid;
  end;
  writeln(left);
end;



begin
  while true do begin
    readln(n,m);
    if n=0 then break;
    work;
  end;
end.
View Code

POJ - 2749 Building roads

每两个点有四种情况:第一个点连s1第二个点s1;第一个点连s1第二个点连s2;第一个点连s2第二个点连s1;第一个点连s2第二个点连s2。

然后二分最大值,如果两个点在上面四种情况的某一种情况中>最大值就不能有这种情况,也就是要选择其他种(具体看程序吧)

type
  arr=record
    toward,next:longint;
  end;

const
  maxm=3000000;
  maxn=90000;
  mm=23333333;

var
  edge:array[0..maxm]of arr;
  low,dfn,first,scc,p:array[0..maxn]of longint;
  num,num1,num2:array[0..maxn,1..2]of longint;
  chose:array[0..maxn]of boolean;
  time,tot,n,m1,m2,tail,sum,dis:longint;

procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  inc(tail);
  p[tail]:=x;
  chose[x]:=true;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    repeat
      too:=p[tail];
      chose[too]:=false;
      scc[too]:=sum;
      dec(tail);
    until x=too;
  end;
end;

function check(x:longint):boolean;
var
  i,j:longint;
begin
  fillchar(dfn,sizeof(dfn),0);
  fillchar(low,sizeof(low),0);
  fillchar(first,sizeof(first),0);
  fillchar(chose,sizeof(chose),false);
  time:=0;
  tot:=0;
  tail:=0;
  for i:=1 to m1 do begin
    add(num1[i,1],num1[i,2]+n);
    add(num1[i,2],num1[i,1]+n);
    add(num1[i,1]+n,num1[i,2]);
    add(num1[i,2]+n,num1[i,1]);
  end;
  for i:=1 to m2 do begin
    add(num2[i,1],num2[i,2]);
    add(num2[i,2],num2[i,1]);
    add(num2[i,1]+n,num2[i,2]+n);
    add(num2[i,2]+n,num2[i,1]+n);
  end;
  for i:=1 to n-1 do
    for j:=i+1 to n do begin
      if num[i,1]+num[j,1]>x then begin
        add(i,j+n);
        add(j,i+n);
      end;
      if num[i,1]+num[j,2]+dis>x then begin
        add(i,j);
        add(j+n,i+n);
      end;
      if num[i,2]+num[j,1]+dis>x then begin
        add(i+n,j+n);
        add(j,i);
      end;
      if num[i,2]+num[j,2]>x then begin
        add(i+n,j);
        add(j+n,i);
      end;
    end;
  for i:=1 to n<<1 do
    if dfn[i]=0 then tarjan(i);
  for i:=1 to n do
    if scc[i]=scc[i+n] then exit(false);
  exit(true);
end;

procedure into;
var
  i,sx1,sy1,sx2,sy2,j,k:longint;
begin
  readln(n,m1,m2);
  read(sx1,sy1,sx2,sy2);
  dis:=abs(sx1-sx2)+abs(sy1-sy2);
  for i:=1 to n do begin
    readln(j,k);
    num[i,1]:=abs(j-sx1)+abs(k-sy1);
    num[i,2]:=abs(j-sx2)+abs(k-sy2);
  end;
  for i:=1 to m1 do
    readln(num1[i,1],num1[i,2]);
  for i:=1 to m2 do
    readln(num2[i,1],num2[i,2]);
end;

procedure work;
var
  left,right,mid:longint;
begin
  left:=0;
  right:=mm;
  while left<right do begin
    mid:=(left+right)>>1;
    if check(mid) then right:=mid
      else left:=mid+1;
  end;
  if left>=mm then writeln(-1)
    else writeln(left)
end;

begin
  into;
  work;
end.
View Code

bzoj1823: [JSOI2010]满汉全席

我去这题好水……题目老长结果&……

直接连通判断就行了

type
  arr=record
    toward,next:longint;
  end;
 
const
  maxm=50000;
  maxn=2000;
 
var
  dfn,low,first,scc,p:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  time,tot,n,m,tail,sum,t:longint;
  edge:array[0..maxm]of arr;
 
 
procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;
 
procedure tarjan(x:longint);
var
  i,too:longint;
begin
  inc(time);
  dfn[x]:=time;
  low[x]:=time;
  chose[x]:=true;
  inc(tail);
  p[tail]:=x;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if dfn[too]=0 then begin
      tarjan(too);
      if low[x]>low[too] then low[x]:=low[too];
    end
    else
      if chose[too] and (dfn[too]<low[x]) then low[x]:=dfn[too];
    i:=edge[i].next;
  end;
  if low[x]=dfn[x] then begin
    inc(sum);
    repeat
      too:=p[tail];
      dec(tail);
      chose[too]:=false;
      scc[too]:=sum;
    until x=too;
  end;
end;
 
procedure into;
var
  i,x1,x2,y1,y2:longint;
  ch:char;
begin
  readln(n,m);
  fillchar(dfn,sizeof(dfn),0);
  fillchar(low,sizeof(low),0);
  fillchar(first,sizeof(first),0);
  fillchar(chose,sizeof(chose),false);
  tot:=0;
  time:=0;
  tail:=0;
  for i:=1 to m do begin
    read(ch);
    read(x1);
    if ch='m' then begin
      x2:=x1;
      x1:=x1+n;
    end
    else x2:=x1+n;
    read(ch);
    read(ch);
    readln(y1);
    if ch='m' then begin
      y2:=y1;
      y1:=y1+n;
    end
    else y2:=y1+n;
    add(x2,y1);
    add(y2,x1);
  end;
end;
 
function work:boolean;
var
  i:longint;
begin
  for i:=1 to n<<1 do
    if dfn[i]=0 then tarjan(i);
  for i:=1 to n do
    if scc[i]=scc[i+n] then exit(false);
  exit(true);
end;
 
begin
  readln(t);
  while t>0 do begin
    dec(t);
    into;
    if work then writeln('GOOD')
      else writeln('BAD');
  end;
end.
View Code

bzoj2199: [Usaco2011 Jan]奶牛议会

这题……求的不是某组解的答案而是奇奇怪怪的东西……那就用那个o(nm)的方法判断吧!

type
  arr=record
    toward,next:longint;
  end;
 
const
  maxn=2333;
  maxm=50000;
 
var
  edge:array[0..maxm]of arr;
  chose:array[0..maxn]of boolean;
  first:array[0..maxn]of longint;
  ans:array[0..maxn]of 0..2;
  n,m,tot:longint;
 
procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;
 
procedure dfs(x:longint);
var
  i,too:longint;
begin
  chose[x]:=true;
  i:=first[x];
  while i>0 do begin
    too:=edge[i].toward;
    if not chose[too] then dfs(too);
    i:=edge[i].next;
  end;
end;
 
function check(x:longint):boolean;
var
  i:longint;
begin
  fillchar(chose,sizeof(chose),false);
  dfs(x);
  for i:=1 to n do
    if chose[i] and chose[i+n] then exit(false);
  exit(true);
end;
 
procedure into;
var
  x1,x2,y1,y2,i:longint;
  ch:char;
begin
  readln(n,m);
  for i:=1 to m do begin
    read(x1);
    read(ch);
    read(ch);
    if ch='Y' then x2:=x1+n
    else begin
      x2:=x1;
      x1:=x1+n;
    end;
    read(y1);
    read(ch);
    readln(ch);
    if ch='Y' then y2:=y1+n
    else begin
      y2:=y1;
      y1:=y1+n;
    end;
    add(x2,y1);
    add(y2,x1);
  end;
end;
 
procedure work;
var
  i:longint;
  ok1,ok2:boolean;
begin
  for i:=1 to n do begin
    ok1:=check(i);
    ok2:=check(i+n);
    if not (ok1 or ok2) then begin
      writeln('IMPOSSIBLE');
      exit; 
    end;
    if ok1 then
      if ok2 then ans[i]:=0
        else ans[i]:=1
    else ans[i]:=2;
  end;
  for i:=1 to n do
    case ans[i] of
      0:write('?');
      1:write('Y');
      2:write('N');
    end;
end;
 
 
begin
  into;
  work;
end.
View Code

hdu 1814 Peaceful Commission

这题的读入我也是醉了……似乎没有说是多组数据啊结果……调了一节晚自修后才发现……

因为要字典序最小所以用白书中的方法……

建图一样有点傻,我是把点认为是人……结果大家都是把点认为是党员……然后我就华丽丽地把节点数升级到了4n……

type
  arr=record
    toward,next:longint;
  end;

const
  maxn=60000;
  maxm=2000000;

var
  first,p:array[0..maxn]of longint;
  edge:array[0..maxm]of arr;
  color:array[0..maxn]of boolean;
  tail,tot,n,m,long,i:longint;

procedure add(j,k:longint);
begin
  inc(tot);
  edge[tot].toward:=k;
  edge[tot].next:=first[j];
  first[j]:=tot;
end;

function dfs(x:longint):boolean;
var
  i,too:longint;
  flag:boolean;
begin
  if color[x+long] then dfs:=false
  else
  if color[x] then dfs:=true
  else begin
    flag:=true;
    color[x]:=true;
    inc(tail);
    p[tail]:=x;
    i:=first[x];
    while i>0 do begin
      too:=edge[i].toward;
      if not dfs(too) then begin
        flag:=false;
        break;
      end;
      i:=edge[i].next;
    end;
    dfs:=flag;
  end;
end;

procedure into;
var
  i,j,k:longint;
begin
  fillchar(color,sizeof(color),false);
  fillchar(first,sizeof(first),0);
  tail:=0;
  long:=n*2;
  tot:=0;
  for i:=1 to n do begin
    j:=i*2;
    add(j-1,j+long);
    add(j+long,j-1);
    add(j,j-1+long);
    add(j-1+long,j);
  end;
  for i:=1 to m do begin
    readln(j,k);
    add(j,k+long);
    add(k,j+long);
  end;
end;

function work:boolean;
var
  i,j:longint;
  flag:boolean;
begin
  flag:=true;
  for i:=1 to long do
    if not (color[i] or color[i+long]) then begin
      tail:=0;
      if not dfs(i) then begin
        for j:=tail downto 1 do color[p[j]]:=false;
        if not dfs(i+long) then begin
          flag:=false;
          break;
        end;
      end;
    end;
  work:=flag;
end;

begin
  while not eof do begin
    readln(n,m);
    into;
    if work then begin
      for i:=1 to long do
        if color[i] then writeln(i);
    end
    else writeln('NIE');
  end;
end.
View Code
原文地址:https://www.cnblogs.com/Macaulish/p/4185683.html