[BZOJ1997][HNOI2010]Planar

bzoj
luogu

题意

给你一张含有一条哈密顿回路的无向图(哈密顿回路就是经过每个店恰好一次),判断这张图是不是平面图(平面图就是可以画在平面上使边不相交)。

sol

首先有一个平面图定理:一张平面图的边数不超过\(3N-6\)(其中\(N\)是点数)
这样就把边数降到了\(O(n)\)级别。
把环抠出来,剩下的边就只能从环的里面连或者从环的外面连。
问题转化成\(2-sat\)
直接\(O(n^2)\)建边即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi()
{
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 605;
const int M = 4e5+5;
struct edge{int u,v;}E[M];
int T,n,m,p[N],tot,to[M],nxt[M],head[N],cnt,dfn[N],low[N],tim,Stack[N],top,vis[N],bel[N],scc;
bool Cross(int l1,int r1,int l2,int r2)
{
	if (l1>l2) swap(l1,l2),swap(r1,r2);
	return l1<l2&&l2<r1&&r1<r2;
}
void link(int u,int v)
{
	to[++cnt]=v;nxt[cnt]=head[u];
	head[u]=cnt;
}
void Tarjan(int u)
{
	dfn[u]=low[u]=++tim;
	Stack[++top]=u;vis[u]=1;
	for (int e=head[u];e;e=nxt[e])
		if (!dfn[to[e]]) Tarjan(to[e]),low[u]=min(low[u],low[to[e]]);
		else if (vis[u]) low[u]=min(low[u],dfn[to[e]]);
	if (dfn[u]==low[u])
	{
		++scc;int v;
		do{
			v=Stack[top--];
			vis[v]=0;bel[v]=scc;
		}while (u!=v);
	}
}
bool check()
{
	for (int i=1;i<=tot;++i)
		if (bel[i]==bel[i+tot]) return false;
	return true;
}
int main()
{
	T=gi();
	while (T--)
	{
		memset(head,0,sizeof(head));
		memset(dfn,0,sizeof(dfn));
		cnt=tot=scc=tim=0;
		n=gi();m=gi();
		for (int i=1;i<=m;++i) E[i]=(edge){gi(),gi()};
		for (int i=1;i<=n;++i) p[gi()]=i;
		if (m>3*n-6) {puts("NO");continue;}
		for (int i=1;i<=m;++i)
		{
			E[i].u=p[E[i].u];E[i].v=p[E[i].v];
			if (E[i].u>E[i].v) swap(E[i].u,E[i].v);
			if (E[i].u+1!=E[i].v&&!(E[i].u==1&&E[i].v==n)) E[++tot]=E[i];
		}
		for (int i=1;i<=tot;++i)
			for (int j=i+1;j<=tot;++j)
				if (Cross(E[i].u,E[i].v,E[j].u,E[j].v))
					link(i,j+tot),link(j,i+tot),link(i+tot,j),link(j+tot,i);
		for (int i=1;i<=(tot<<1);++i) if (!dfn[i]) Tarjan(i);
		puts(check()?"YES":"NO");
	}
	return 0;
}
posted @ 2018-03-31 14:21  租酥雨  阅读(209)  评论(0编辑  收藏  举报