算是比较经典的2-SAT模型了吧。
题意很多人都没说清楚,我这里贴一个别人的题解,这里面的说的很好。
http://blog.csdn.net/l04205613/article/details/6668318
2-sat直接上,连边的时候直接把a1
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=5e5+5;
int n,m;
int a[N],b[N],head[N],next[N],go[N];
bool ins[N];
int low[N],dfn[N],stk[N];
int top,tim,bl,tot,block[N];
inline void tarjan(int x)
{
dfn[x]=low[x]=++tim;
stk[++top]=x;
ins[x]=1;
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if (ins[v])low[x]=min(dfn[v],low[x]);
}
if (dfn[x]==low[x])
{
bl++;
int j=0;
while (j!=x)
{
j=stk[top--];
block[j]=bl;
ins[j]=0;
}
}
}
inline bool jud()
{
fo(i,1,m)
if (block[2*i]==block[2*i-1])return 0;
return 1;
}
inline void add(int x,int y)
{
go[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
inline void build()
{
fo(i,1,m)
fo(j,i+1,m)
if ((a[i]<a[j]&&a[j]<b[i]&&b[j]>b[i])||(a[j]<a[i]&&a[i]<b[j]&&b[i]>b[j]))
{
add(2*i-1,2*j);
add(2*j,2*i-1);
add(2*j-1,2*i);
add(2*i,2*j-1);
}
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,1,m)
{
scanf("%d%d",&a[i],&b[i]);
if (a[i]>b[i])swap(a[i],b[i]);
}
build();
fo(i,1,2*m)if (!dfn[i])tarjan(i);
if (jud())puts("panda is telling the truth...");
else puts("the evil panda is lying again");
}