POJ3207

典型的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;
}

猜你喜欢

转载自blog.csdn.net/Amuseir/article/details/80024746
今日推荐