看了半天,看不懂题意。
题意
在一个圆上分布有n个点,现在要在这n个点之间连上m条边,每条边可以从圆内连接,也可以在圆外连接,每个点只能连接一条边,求是否存在连接方案能使得这m条边不相交。
看图容易懂题意。。。。。。
那么
对于两条线(这道题的节点可以认为是线,i<<1表示第i条线外连,i<<1|1表示第i条线内连。),矛盾的必要条件是(不妨设line[i].a< line[j].a)
line[j].a< line[i].b&&line[i].b< line[j].b。满足这个必要条件并不一定矛盾,只需(i内连&&j外连)||(i外连&&j内连)
看似不是2-sat问题,其实
转化一下(数理逻辑的知识),就等于
(i内连||j内连)&&(i外连||j外连)
2-sat问题就是一个合取范式。
所以就相当于两个析取式(i内连||j内连)和(i外连||j外连)。
接着就是2-sat问题的解法了。
由于这道题只需判断是否矛盾,所以就可以直接求强连通,然后看是否有某个Belong[i<<1]和Belong[i<<1|1](对于这道题,每条线只能选择内连或者外连之一,也就相当于要么内连为真,要么内连为假两种情况,用i<<1代表内连为真,i<<1|1代表内连为假,如果他们在一个强连通分量中则说明他们要么同时取,要么同时不去,但是它们事实上必须取并且只能取其中一个。)是否相等。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=1010;
const int MAXM=1e6+5;
struct _Edge
{
int to,next;
}edge[MAXM];
int hd[MAXN],tot;
void inti(void)
{
tot=0;
msc(hd);
}
void addedge(int u,int v)
{
edge[tot].to=v,edge[tot].next=hd[u];
hd[u]=tot++;
//printf(" %d to %d\n",u,v );
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool Instack[MAXN];
void Tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=hd[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
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])
{
scc++;
do{
v=Stack[--top];
Instack[v]=false;
Belong[v]=scc;
}while(v!=u);
}
}
struct _Line
{
int a,b;
}line[MAXN>>1];
int cmp(const void *p,const void *q)
{return ((struct _Line *)p)->a-((struct _Line *)q)->a;}
int main(int argc, char const *argv[])
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
if(a<b) line[i].a=a,line[i].b=b;
else line[i].a=b,line[i].b=a;
}
qsort(line,m,sizeof(struct _Line),cmp);
inti();
for(int i=0;i<m;i++)
for(int j=i+1;j<m;j++)
if(line[j].a<line[i].b&&line[i].b<line[j].b)
{
addedge(i<<1,j<<1|1);
addedge(j<<1,i<<1|1);
addedge(i<<1|1,j<<1);
addedge(j<<1|1,i<<1);
}
ms(DFN);
ms(Instack);
Index=scc=top=0;
for(int i=0;i<2*m;i++)
if(!DFN[i]) Tarjan(i);
for(int i=0;i<2*m;i+=2)
if(Belong[i]==Belong[i^1])
{
puts("the evil panda is lying again");
return 0;
}
puts("panda is telling the truth...");
return 0;
}
/*
6 3
0 3
1 4
2 5
*/