Description
Input
Output
Sample Input
2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5
Sample Output
NO
YES
题解
第一次做有关平面图的问题
先记下一个结论:对于一个极大简单平面图G(n,m),总有m<=3*n-6
发现如果两条线段在圈内会相交,在圈外也会相交
暴力枚举两条线段判相交情况,建边2-sat判可行性
m很大但可以用上面那个结论剪枝
就愉快地 n2 n 2 啦
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct pt{int c,op;}g[15];
bool cmp(pt n1,pt n2){return (n1.c!=n2.c)?(n1.c<n2.c):(n1.op<n2.op);}
struct edge{int x,y;}w[10005];
struct node{int x,y,next;}a[400005];int len,last[1205];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int low[1205],dfn[1205],sta[1205],belong[1205],id,cnt,tp,n,m;
bool v[1205];
void tarjan(int x)
{
low[x]=dfn[x]=++id;sta[++tp]=x;
v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==-1)tarjan(y),low[x]=min(low[x],low[y]);
else if(v[y])low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
int i;cnt++;
do
{
i=sta[tp--];
belong[i]=cnt;
v[i]=false;
}while(i!=x);
}
}
int ring[1205],pos[1205];
bool check(int x,int y)
{
int u=pos[x];
if(ring[u+1]!=y&&ring[u-1]!=y)return true;
return false;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d",&w[i].x,&w[i].y);
for(int i=1;i<=n;i++)scanf("%d",&ring[i]),pos[ring[i]]=i;
ring[0]=ring[n];ring[n+1]=ring[1];
if(m>3*n-6){puts("NO");continue;}
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=m;i++)
if(check(w[i].x,w[i].y))
for(int j=i+1;j<=m;j++)
if(check(w[j].x,w[j].y))
{
int s1=pos[w[i].x],s2=pos[w[i].y];if(s1>s2)swap(s1,s2);
int s3=pos[w[j].x],s4=pos[w[j].y];if(s3>s4)swap(s3,s4);
if(s1==s3||s1==s4||s2==s3||s2==s4)continue;
g[1].c=s1;g[1].op=1;g[2].c=s2;g[2].op=1;
g[3].c=s3;g[3].op=2;g[4].c=s4;g[4].op=2;
sort(g+1,g+1+4,cmp);
if(g[1].op==g[3].op)ins(i,j+m),ins(i+m,j),ins(j,i+m),ins(j+m,i);
}
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(v,false,sizeof(v));
id=cnt=tp=0;
for(int i=1;i<=2*m;i++)if(dfn[i]==-1)tarjan(i);
bool bk=true;
for(int i=1;i<=m;i++)if(belong[i]==belong[i+m]){bk=false;break;}
if(bk)puts("YES");
else puts("NO");
}
return 0;
}