题意:
给一个n个点大环,大环上有边,问这个图是不是平面图。
(n≤200,m≤10000)
题解:
二分图染色判断合法性很好想,但
m
这么大不可能
听说有一个平面图定理:若图是平面图,那么
m≤3∗n−6
。
那么直接剪枝 n2 判定就好了。
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
const int Maxn=2e2+50,Maxm=1e4+50;
int T,n,m,pos[Maxn],anc[Maxm<<1];
inline int getanc(int x){return (anc[x]==x)?x:(anc[x]=getanc(anc[x]));}
struct edge{int x,y;}edge[Maxm];
inline bool judge_valid(int x,int y){
int t1=pos[edge[x].x],t2=pos[edge[x].y],t3=pos[edge[y].x],t4=pos[edge[y].y];
if(t1>t2)swap(t1,t2);
return (t3>=t1&&t3<=t2&&t4>=t1&&t4<=t2)||((t3<=t1||t3>=t2)&&(t4<=t1||t4>=t2));
}
int main(){
T=read();
while(T--){
n=read(),m=read();
for(int i=1;i<=m;i++){
edge[i].x=read();
edge[i].y=read();
}
for(int i=1;i<=n;i++)pos[read()]=i;
if(m>3*n-6)puts("NO");
else{
int bz=1;
for(int i=1;i<=m;i++)anc[i]=i,anc[i+m]=i+m;
for(int i=1;i<=m&&bz;i++){
for(int j=1;j<i&&bz;j++){
if(!judge_valid(i,j)){
int t1=getanc(i),t2=getanc(j),t3=getanc(i+m),t4=getanc(j+m);
if(t1==t2||t3==t4){
puts("NO");bz=0;
break;
}
anc[t1]=t4;anc[t2]=t3;
}
}
}
if(bz)puts("YES");
}
}
}