典型的2-SAT题目,在一边画圆弧的时候就把中间的点全部连到外面去,然后缩点后判断是否存在矛盾解(环)即可
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=5e4+5;
int n,m;
struct Edge
{
int nxt;
int to;
}edge[MAXN<<1];
int a[MAXN];
int b[MAXN];
int head[MAXN<<1];
int num;
void add(int from,int to)
{
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
void add_edge(int from,int to)
{
add(from,to);
}
int indx;
int cnt;
int color[MAXN];
int top;
int stk[MAXN];
int dfn[MAXN];
int low[MAXN];
bool vis[MAXN];
void tarjan(int x)
{
indx++;
low[x]=dfn[x]=indx;
stk[++top]=x;
vis[x]=1;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[v],low[x]);
}
else
{
if(vis[v])
{
low[x]=min(low[x],dfn[v]);
}
}
}
if(low[x]==dfn[x])
{
cnt++;
while(1)
{
int u=stk[top--];
vis[u]=0;
color[u]=cnt;
if(u==x)
{
break;
}
}
}
}
bool solve()
{
for(int i=1;i<=m;i++)
{
if(color[i]==color[i+m])
{
return false;
break;
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&a[i],&b[i]);
if(a[i]>b[i])
{
swap(a[i],b[i]);
}
}
int mm=m*2;
for(int i=1;i<=m;i++)
{
for(int j=1;j<i;j++)
{
if((a[i] <= a[j] && b[i] >= a[j] && b[i] <= b[j]) || (a[i] >= a[j] && a[i] <= b[j] && b[i] >= b[j]))
{
add_edge(i,j+m);
add_edge(j+m,i);
add_edge(i+m,j);
add_edge(j,i+m);
}
}
}
for(int i=1;i<=mm;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
if(solve())
{
printf("panda is telling the truth...\n");
}
else
{
printf("the evil panda is lying again\n");
}
return 0;
}