• 解题报告 poj 3207


    1.        题目

    POJ 3207

    2.        题目实质

    平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。问能不能连接这m条边,使这些边都不相交。(比如两条边分别是1-2,2-3,则可以连接。若有三条边分别时1-5,2-6,3-7则一定会出现相交)。

    3.        算法

    2-SAT。(NOI)

    题意可能刚开始不是很好理解,比如1 5连边,2,6连边,由于点是顺序排列的,一画图就可以发现,这两条边必须一个从圆外面连,一个从内部连,否则就会相交。如果再加入3 7这条边,那么就必须相交了。

    这样,就可以转化成标准的2-sta问题:

    1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'

    2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以)

    那么连边:

    i->j’, 表示i画内部的话,j只能画外部,即j’

    j->i’,同理

    i’->j,同理

    j’->i,同理

    然后就是2-sat算法了,tarjan一下,如果有i和i'同属于一个强联通,返回false,否则就成立。

    4.        注意事项

    对于 NOIP 的孩子们来说, tarjan 素超纲滴。

    5.        代码

    2-sat (ZSZ)

    program fot;

    var belong,l,r:array[0..500010] of longint;

        instack:array[0..500010] of boolean;

        low,dfn,stack,f:array[0..500010] of longint;

        e:Array[0..500010] of record

          y,n:longint;

        end;

        o,i,n,top,j,m,time,number,q,z:longint;

        boo:boolean;

    function min(a,b:longint):longint;

    begin

      if a<b then exit(a) else exit(b);

    end;

    procedure swap(var a,b:longint);

    var c:longint;

    begin

      c:=a;a:=b;b:=c;

    end;

    procedure add(a,b:longint);

    begin

      inc(o);

      e[o].y:=b;

      e[o].n:=f[a];

      f[a]:=o;

    end;

    procedure tarjan(x:longint);

    var t:longint;

    begin

      inc(time);

      dfn[x]:=time;

      low[x]:=time;

      inc(top);

      instack[x]:=true;

      stack[top]:=x;

      t:=f[x];

      while t<>0 do

        begin

          if (dfn[e[t].y]=0) then

            begin

              tarjan(e[t].y);

              low[x]:=min(low[x],low[e[t].y]);

            end

          else

          if instack[e[t].y]=true then

            low[x]:=min(low[x],dfn[e[t].y]);

          t:=e[t].n;

        end;

      if dfn[x]=low[x] then

        begin

          inc(number);

          repeat

            t:=stack[top];

            dec(top);

            instack[t]:=false;

            belong[t]:=number;

          until t=x;

        end;

    end;

    begin

      readln(n,m);

      for i:= 1 to m do

        begin

          readln(l[i],r[i]);

          if (r[i]<l[i]) then swap(r[i],l[i]);

        end;

      o:=0;

      fillchar(e,sizeof(e),0);

      fillchar(f,sizeof(f),0);

      fillchar(dfn,sizeof(dfn),0);

      fillchar(stack,sizeof(stack),0);

      fillchar(low,sizeof(low),0);

      fillchar(belong,sizeof(belong),0);

      fillchar(instack,sizeof(instack),false);

      for i:= 1 to m do

        for j:= i+1 to m do

          begin

            if ((l[i]>l[j])and(l[i]<r[j])and(r[i]>r[j]))or

            ((l[j]>l[i])and(l[j]<r[i])and(r[j]>r[i])) then

              begin

                add(i,j+m);

                add(j+m,i);

                add(j,i+m);

                add(i+m,j);

              end;

          end;

      top:=0;

      for i:= 1 to 2*m do

        if dfn[i]=0 then tarjan(i);

      boo:=true;

      for i:= 1 to m do

        if belong[i]=belong[i+m] then

          begin

            boo:=false;

            break;

          end;

      if boo=true then writeln('panda is telling the truth...')

      else writeln('the evil panda is lying again');

    end.

     

  • 相关阅读:
    LeetCode 15 3Sum
    R语言函数化学习笔记6
    R语言函数化学习笔记4
    R语言函数化学习笔记3
    R语言函数化编程笔记2
    R语言读写数据
    R语言函数化编程笔记1
    服务&软件&基础设施的区别
    网易云热评1很扎心
    滞后项
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2215523.html
Copyright © 2020-2023  润新知