题意
分析
首先这题有一个很棒棒的结论,就是如果m>n*3-6的话那么这个图一定不是平面图。证明的话。。。据说离散书上面有。
那么我们就可以将边数变为600的大小。
注意到因为这是一个环,所以一条边要么在环内,要么在环外。所以对于两条相交的边,肯定是一条在环内,一条在环外。那么只要暴力2-SAT建图+判定就好了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1205;
int n,m,cnt,last[N],low[N],dfn[N],sta[N],top,bel[N],ins[N],tim,tot,id[N];
struct edge{int to,next;}e[N*N];
struct data{int x,y;}a[10005];
int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void addedge(int u,int v)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
ins[x]=1;sta[++top]=x;
for (int i=last[x];i;i=e[i].next)
if (!dfn[e[i].to])
{
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
else if (ins[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
if (dfn[x]==low[x])
{
tot++;int y=0;
while (y!=x)
{
y=sta[top];top--;
bel[y]=tot;ins[y]=0;
}
}
}
int main()
{
int T=read();
while (T--)
{
n=read();m=read();
for (int i=1;i<=m;i++) a[i].x=read(),a[i].y=read();
for (int i=1;i<=n;i++) id[read()]=i;
for (int i=1;i<=m;i++)
{
a[i].x=id[a[i].x],a[i].y=id[a[i].y];
if (a[i].x>a[i].y) swap(a[i].x,a[i].y);
}
if (m>n*3-6)
{
puts("NO");
continue;
}
cnt=0;memset(last,0,sizeof(last));
for (int i=1;i<m;i++)
for (int j=i+1;j<=m;j++)
if (a[i].x<a[j].x&&a[j].x<a[i].y&&a[i].y<a[j].y||a[j].x<a[i].x&&a[i].x<a[j].y&&a[j].y<a[i].y)
{
addedge(i+m,j);addedge(i,j+m);
}
memset(dfn,0,sizeof(dfn));tot=tim=0;
for (int i=1;i<=m*2;i++)
if (!dfn[i]) tarjan(i);
int flag=0;
for (int i=1;i<=m;i++)
if (bel[i]==bel[i+m])
{
flag=1;break;
}
if (flag) puts("NO");
else puts("YES");
}
return 0;
}