zoukankan      html  css  js  c++  java
  • poj3207:Ikki's Story IV-Panda's Trick【2-sat tarjan】

    题目大意:圆盘上顺次安放0, 1, 2, …, n – 1的点,每次给出两个点需要连边,可以选择在圆盘的正面连边或在圆盘的反面连边,问是否存在一种方案使得所有连线不相交?

    思路:本问题可以等价成:圆盘上原本有N条线,每条线在正反面都有画上,将在正反面的两条线只保留一根,问是否存在一种方案使得所有连线不相交?

    这样问题就成了赤果果的2-SAT问题了,注意到两条线如果都在正面会相交,那么都在反面也会相交,因此构图时应是无向图,按照2-SAT的形式构完图后,用TARJAN求缩点,由于在一个SCC中的点都是必定同时存在的,所以当一个线的正面和反面所代表的点在一个SCC中时,即可判定不存在这样的连线方法,充分性的证明略

    #include<iostream>

    #include<cstdio>

    #include <math.h>

    #define maxn 90000

    #define min(x,y) ((x)<(y)?(x):(y))

    inta[maxn],b[maxn],head[maxn],point[maxn],next[maxn],dfn[maxn],stack[maxn],now=0;

    bool instack[maxn];

    intcount=0,num=1,belong[maxn],low[maxn],top=0;

    void insert(int x,int y)

    {

       next[++now]=head[x];

       head[x]=now;

       point[now]=y;

    }

    void tarjan(int k)

    {

       int u;

       instack[k]=true;

       stack[++top]=k;

       dfn[k]=low[k]=++num;

       for(int i=head[k];i!=0;i=next[i])

        {

           u=point[i];

           if (dfn[u]==0)

           {

               tarjan(u);

               low[k]=min(low[k],low[u]);

           }

           else if (instack[u])low[k]=min(low[k],dfn[u]);

        }

       if (low[k]==dfn[k])

        {

           ++count;

           do

           {

               u=stack[top--];

               instack[u]=false;

               belong[u]=count;

           }while(u!=k);

        }

    }

    int main()

    {

       int n,m,temp,flag=0;

       scanf("%d%d",&n,&m);

       for(int i=1;i<=m;i++)

        {

           scanf("%d%d",&a[i],&b[i]);

           if (a[i]>b[i]){temp=a[i];a[i]=b[i];b[i]=temp;}

        }

       for (int i=1;i<=m-1;i++)//build graph

        {

           for(int j=i+1;j<=m;j++)

           {

               if ((a[i]<a[j] && b[j]>b[i]&&a[j]<b[i])||(a[i]>a[j] && b[j]<b[i]&&a[i]<b[j]))

               {

                   insert(i*2,j*2+1);insert(j*2+1,i*2);

                   insert(i*2+1,j*2);insert(j*2,i*2+1);

               }

           }

        }

       for (int i=1;i<=2*m;i++)if (dfn[i]==0)tarjan(i);

       for(int i=1;i<=m;i++)if (belong[i*2]==belong[i*2+1]){flag=1;break;}

       if (flag==0)printf("panda is telling the truth... ");

       else printf("the evil panda is lying again ");

       return 0;

    }

  • 相关阅读:
    Flexcell 导出Excel 打不开,提示Excel在“XXXX.xls” 中发现不可读取的内容。是否要回复此工作薄的内容?如果信任此工作薄的来源,请点击“是”。
    文件上传
    ssrf
    信息收集
    xss
    SQL注入
    Apache Flink CVE-2020-17519漏洞复现
    activemq
    centos6使用yum快速搭建LAMP
    Fastjson<=1.2.47反序列化漏洞复现
  • 原文地址:https://www.cnblogs.com/philippica/p/4006997.html
Copyright © 2011-2022 走看看