码迷,mamicode.com
首页 > 其他好文 > 详细

poj3207:Ikki's Story IV-Panda's Trick【2-sat tarjan】

时间:2014-10-05 14:43:28      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:io   os   ar   for   sp   问题   c   on   amp   

题目大意:圆盘上顺次安放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...\n");

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

   return 0;

}

poj3207:Ikki's Story IV-Panda's Trick【2-sat tarjan】

标签:io   os   ar   for   sp   问题   c   on   amp   

原文地址:http://www.cnblogs.com/philippica/p/4006997.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!