题目描述
题意:给出圆上的n个点,某些点之间有连线,连线可以从圆内也可以从圆外连,问是否存在一种方案使所有的连线不相交(相交在圆上的除外)。
题解
很显然的2-SAT问题
对于每一对点有两个选择:从圆内连和从圆外连
限制:连线不能相交
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 500005
int n,m,dfs_clock,scc,top;
int tot,point[N],nxt[N],v[N];
int x[N],y[N],dfn[N],low[N],belong[N],stack[N],vis[N];
bool flag;
void add(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void tarjan(int x)
{
dfn[x]=low[x]=++dfs_clock;stack[++top]=x;vis[x]=1;
for (int i=point[x];i;i=nxt[i])
if (!dfn[v[i]])
{
tarjan(v[i]);
low[x]=min(low[x],low[v[i]]);
}
else if (vis[v[i]])
low[x]=min(low[x],dfn[v[i]]);
if (dfn[x]==low[x])
{
int now=0;++scc;
while (now!=x)
{
now=stack[top--];
belong[now]=scc;
vis[now]=0;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x[i],&y[i]);
if (x[i]>y[i]) swap(x[i],y[i]);
}
for (int i=1;i<=m;++i)
for (int j=i+1;j<=m;++j)
if (x[j]<y[i]&&x[j]>x[i]&&y[i]<y[j]||x[i]<y[j]&&x[i]>x[j]&&y[j]<y[i])
add(i,j+m),add(j,i+m),add(i+m,j),add(j+m,i);
for (int i=1;i<=2*m;++i)
if (!dfn[i]) tarjan(i);
flag=true;
for (int i=1;i<=m;++i)
if (belong[i]==belong[i+m])
{flag=false;break;}
if (flag) puts("panda is telling the truth...");
else puts("the evil panda is lying again");
}