POJ--3207[Ikki's Story IV - Panda's Trick] 第一道2—SAT

来源:互联网 发布:mac玩gta5爆了 编辑:程序博客网 时间:2024/04/29 17:39
题目大意:

一个圆盘上有n个点,编号顺次为0……n-1,现在给出m条线段,这些线段可以在盘的正面,也可以在反面,要求判断最终是否有线段不相交的安排,使满足要求.

 

思路分析:
      令第i条线(i从0开始)在正面为第2i个顶点,在反面为第2i+1个顶点.若第i条线和第j条线构成一个四边形的两条对角线,则在2i和2j+1之间连一条双向边,2i+1和2j之间连一条双向边.这样建图后求强连通分量,看点2i和点2i+1是否在同一个强连通分量中,如果是在同一强连通分量中,就说明不满足要求,如果没有则满足.
      首先,我们知道若第i条线和第j条线构成一个四边形的两条对角线,则2i和2j不相容,又2i和2i+1中必须出现一个,且2j和2j+1中也必须出现一个,所以可以说2i+1和2j+1中至少出现一个,换句话说, 从2i到2j+1连一条有向边表示如果选择了2i就必须选择2j+1,从2j到2i+1连一条有向边表示如果选择了2j就必须选择2i+1,同理对于2i+1和2j+1的不相容也可以连两条有向边,所以最后跟上面的组成了两条双向边.

 

CODE:

/*POJ第一道2-SAT*//*每一条线看成图上一个点*//*AC代码:0ms*/#include <iostream>#define MAXN 1005#define MAXM 200000struct edge{int v,next;edge(){}edge(int v1,int next1):v(v1),next(next1){}}E[MAXM];int head[MAXN],ecnt;int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];bool Instack[MAXN];int Index,cnt,top,N,M;int a[MAXN],b[MAXN];void Insert(int u,int v){E[ecnt]=edge(v,head[u]);head[u]=ecnt++;}void swap(int &a,int &b){if(a>b){int t=a;a=b;b=t;}}void Build_Map()//构图{int i,j;memset(head,-1,sizeof(head));ecnt=0;for(i=0;i<M;i++){scanf("%d%d",&a[i],&b[i]);swap(a[i],b[i]);//节点是顺时针排列的}for(i=0;i<M;i++){for(j=i+1;j<M;j++){//判断编号为i,j的两条线段是否相交if((a[i]<a[j]&&b[i]<b[j]&&a[j]<b[i])||(a[i]>a[j]&&b[i]>b[j]&&a[i]<b[j])){Insert(2*i,2*j+1);Insert(2*j+1,2*i);//不能去掉Insert(2*j,2*i+1);Insert(2*i+1,2*j);}}}}void Tarjan(int u){int v,i;Low[u]=DFN[u]=++Index;Stack[++top]=u;Instack[u]=true;for(i=head[u];i!=-1;i=E[i].next){v=E[i].v;if(!DFN[v]){Tarjan(v);if(Low[u]>Low[v])Low[u]=Low[v];}else if(Instack[v]&&Low[u]>DFN[v])Low[u]=DFN[v];}if(Low[u]==DFN[u]){cnt++;do{v=Stack[top--];Instack[v]=false;Belong[v]=cnt;}while(u!=v);}return;}bool SAT(){int i;memset(Instack,false,sizeof(Instack));memset(DFN,0,sizeof(DFN));memset(Low,0,sizeof(Low));cnt=top=Index=0;for(i=0;i<2*M;i++)if(!DFN[i])Tarjan(i);for(i=0;i<M;i++)if(Belong[2*i]==Belong[2*i+1])return false;return true;}int main(){scanf("%d%d",&N,&M);Build_Map();if(SAT())printf("panda is telling the truth...\n");elseprintf("the evil panda is lying again\n");return 0;}