zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    7503E-M-irf2配置以及bfd配置
    nltk_29_pickle保存和导入分类器
    nltk_28Twitter情感分析模型
    美国在研新药_读取单个PDF
    Python:eval的妙用和滥用
    opencv_判断两张图片是否相同
    Make 命令教程
    pdf在线处理网站
    K-Means clusternig example with Python and Scikit-learn(推荐)
    自然语言27_Converting words to Features with NLTK
  • 原文地址:https://www.cnblogs.com/Macaulish/p/4185683.html
Copyright © 2011-2022 走看看