题意:
在一个圆上有n个点,m条边将他们相连,问是否有一种连发使没有两条线相交。
分析:
每条线要么在圆内,要么在圆外,2-sat问题。
代码:
//poj 3207
//sep9
#include <iostream>
#include <stack>
using namespace std;
const int maxN=10024;
const int maxM=4200000;
int e,n,m,t,ecnt;
int head[maxN],ins[maxN],low[maxN],dfn[maxN];
int sol[maxN],belong[maxN];
int x[maxN],y[maxN];
stack<int> s;
struct Edge
{
int v,next;
}edge[maxM];
void addegde(int u,int v)
{
edge[e].v=v;edge[e].next=head[u];
head[u]=e++;
}
void dfs(int x)
{
low[x]=dfn[x]=++t;
s.push(x);
ins[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!dfn[v]){
dfs(v);
low[x]=min(low[x],low[v]);
}else if(ins[v]==1)
low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x]){
++ecnt;
int k;
do{
k=s.top();
s.pop();
ins[k]=0;
belong[k]=ecnt;
}while(dfn[k]!=low[k]);
}
}
bool two_sat()
{
memset(ins,0,sizeof(ins));
memset(dfn,0,sizeof(dfn));
while(!s.empty()) s.pop();
int i;
t=0,ecnt=0;
for(i=1;i<=2*n;++i)
if(!dfn[i])
dfs(i);
for(i=1;i<=n;++i)
if(belong[i]==belong[i+n])
return false;
return true;
}
int cross(int i,int j)
{
if(x[i]<x[j]&&x[j]<y[i])
if(y[j]!=x[i]&&y[j]!=y[i])
if(!(x[i]<y[j]&&y[j]<y[i]))
return 1;
if(x[i]<y[j]&&y[j]<y[i])
if(x[j]!=x[i]&&x[j]!=y[i])
if(!(x[i]<x[j]&&x[j]<y[i]))
return 1;
return 0;
}
int main()
{
int i,j,a,b,c;
char op[8];
e=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i){
scanf("%d%d",&x[i],&y[i]);
if(x[i]>y[i])
swap(x[i],y[i]);
}
for(i=1;i<=m;++i)
for(j=1;j<i;++j)
if(cross(i,j)){
addegde(i,j+m);
addegde(i+m,j);
addegde(j,i+m);
addegde(j+m,i);
}
n=m;
bool ans=two_sat();
printf("%s",ans==true?"panda is telling the truth...":"the evil panda is lying again");
return 0;
}