将相交的线连边判断二分图即可。
注意带权并查集的
F
i
n
d
\rm{Find}
Find不能随便用。
A C C o d e \rm{AC Code} ACCode
#include<bits/stdc++.h>
#define maxn 10005
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;
int n,m,x[maxn],y[maxn],d[maxn],pe[maxn],F[maxn],dis[maxn];
int Find(int u){
if(!F[u]) return u;
int f = F[u];
F[u] = Find(F[u]);
dis[u] ^= dis[f];
return F[u];
}
int main(){
int T;
for(scanf("%d",&T);T--;){
scanf("%d%d",&n,&m);
memset(F,0,sizeof F),memset(dis,0,sizeof dis);
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
if(x[i] > y[i]) swap(x[i],y[i]);
}
for(int i=1;i<=n;i++) scanf("%d",&d[i]),pe[d[i]]=i;
if(m > 3 * n - 6){ puts("NO");continue; }
vector<int>p;
for(int i=1;i<=m;i++){
x[i] = pe[x[i]] , y[i] = pe[y[i]];
if(x[i] > y[i]) swap(x[i],y[i]);
if(y[i] != (x[i] % n + 1))
p.pb(i);
}
int g = p.size();
bool ERROR = 0;
for(int i=0;i<g;i++)
for(int j=0;j<g;j++)
if(x[p[i]]<x[p[j]]&&x[p[j]]<y[p[i]]&&y[p[i]]<y[p[j]]){
int a , b;
if((a=Find(p[i])) != (b=Find(p[j]))){
F[a] = b;
dis[a] = dis[p[i]] ^ dis[p[j]] ^ 1;
}
else if(dis[p[i]] == dis[p[j]]) ERROR = 1;
}
if(ERROR) puts("NO");
else puts("YES");
}
}