看到哈密顿回路就被吓傻了……结果没有好好考虑性质……
首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass
然后考虑原图,先把哈密顿回路单独摘出来,就是一个环。对于每一条不在哈密顿回路上的边,有两种可能,一种是在环内,一种是在环外
我们用点来表示每一条边,把每一个点拆成两个分别表示这条边是在环内还是环外。对于两条边$i,j$,如果他们同时在环外或环内会交叉,那么就相当于有了约束条件,转化成一个2-SAT问题即可
至于连边,我们设$i$表示在环内,$i+m$表示在环外,如果$i,j$同在环内或环外会相交,那么连边$(i,j+m),(i+m,j),(j,i+m),(j+m,i)$,即他们永远不能同时在环内或环外
至于如果判断是否会相交,我们可以把环拆开,然后判断同在一侧是否会相交即可
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #define mem(a) (memset(a,0,sizeof(a))) 6 #define swap(x,y) (x^=y^=x^=y) 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf; 10 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} 11 inline int read(){ 12 #define num ch-'0' 13 char ch;bool flag=0;int res; 14 while(!isdigit(ch=getc())) 15 (ch=='-')&&(flag=true); 16 for(res=num;isdigit(ch=getc());res=res*10+num); 17 (flag)&&(res=-res); 18 #undef num 19 return res; 20 } 21 const int N=2e4+5,M=1e5+5; 22 int head[N],Next[M],ver[M],tot; 23 inline void add(int u,int v){ 24 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 25 } 26 int dfn[N],low[N],bl[N],st[N],num,cnt,top,n,m,k; 27 void tarjan(int u){ 28 dfn[u]=low[u]=++num,st[++top]=u; 29 for(int i=head[u];i;i=Next[i]){ 30 int v=ver[i]; 31 if(!dfn[v]) tarjan(v),cmin(low[u],low[v]); 32 else if(!bl[v]) cmin(low[u],dfn[v]); 33 } 34 if(low[u]==dfn[u]) for(++cnt;st[top+1]!=u;--top) bl[st[top]]=cnt; 35 } 36 inline bool check(){ 37 for(int i=1,l=m<<1;i<=l;++i) if(!dfn[i]) tarjan(i); 38 for(int i=1;i<=m;++i) 39 if(bl[i]==bl[i+m]) return false; 40 return true; 41 } 42 int rev[205],cir[205][205],E[205],eu[N],ev[N]; 43 void clear(){ 44 mem(head),mem(dfn),mem(low),mem(bl),mem(st),mem(cir); 45 num=cnt=top=tot=0; 46 } 47 void solve(){ 48 clear(); 49 n=read(),m=read(),k=0; 50 for(int i=1;i<=m;++i){ 51 eu[i]=read(),ev[i]=read(); 52 if(eu[i]>ev[i]) swap(eu[i],ev[i]); 53 } 54 for(int i=1;i<=n;++i){ 55 rev[E[i]=read()]=i; 56 if(i>1){ 57 int u=E[i-1],v=E[i]; 58 u<v?cir[u][v]=1:cir[v][u]=1; 59 } 60 } 61 if(m>3*n-6) return (void)(puts("NO")); 62 for(int i=1;i<=m;++i) 63 if(!cir[eu[i]][ev[i]]) eu[++k]=eu[i],ev[k]=ev[i]; 64 m=k; 65 for(int i=1;i<m;++i) 66 for(int j=i+1;j<=m;++j){ 67 int u=rev[eu[i]],v=rev[ev[i]],x=rev[eu[j]],y=rev[ev[j]]; 68 if(u>v) swap(u,v);if(x>y) swap(x,y); 69 if((u<x&&v>x&&v<y)||(u>x&&u<y&&v>y)){ 70 add(i,j+m),add(j,i+m),add(i+m,j),add(j+m,i); 71 } 72 } 73 puts(check()?"YES":"NO"); 74 } 75 int main(){ 76 // freopen("testdata.in","r",stdin); 77 int T=read(); 78 while(T--) solve(); 79 return 0; 80 }