记集合m+i 为不能和第i条边在同一集合的边 弱i,j相交 且i,j在同一组合 则不合法
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<deque>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 200;
const int MAXM = 10000;
int fa[MAXN*2+10], n, m, X[MAXM+10], Y[MAXM+10], rk[MAXN+10];
int M, G[MAXN+10][MAXN+10], c[MAXN+10], x[MAXM+10], y[MAXM+10];
int find(int x) {
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
inline bool crs(int x1, int y1, int x2, int y2) // 判断是否相交
{
if (x1 == x2 || x1 == y2 || y1 == x2 || y1 == y2) return false;
x1 = rk[x1];
y1 = rk[y1];
x2 = rk[x2];
y2 = rk[y2];
if (x1 > y1) swap(x1, y1);
return (bool)(x1 < x2 && x2 < y1) != (bool)(x1 < y2 && y2 < y1);
}
void check(int m) {
for(int i = 1; i <= m*2; i++) fa[i] = i;
for(int i = 1; i <= m; i++)
for(int j = 1; j <= m; j++)
if(crs(x[i], y[i], x[j], y[j])) {
int fa1 = find(i), fa2 = find(j);
if(fa1 == fa2) {
puts("NO"); return ;
}
fa[fa1] = find(m+j);
fa[fa2] = find(m+i);
}
puts("YES");
}
int main() {
int kase = 0;
int _T; SF("%d", &_T); while(_T--) {
kase++;
int tot = 0;
SF("%d%d", &n, &m);
for(int i = 1; i <= m; i++) SF("%d%d", &X[i], &Y[i]);
for(int i = 1; i <= n; i++) {
SF("%d", &c[i]);
rk[c[i]] = i;
G[c[i]][c[i-1]] = kase;
}
if(m > 3*n-6) {
puts("NO");
continue;
}
for(int i = 1; i <= m; i++) {
if(G[X[i]][Y[i]] != kase) {
tot++;
x[i] = X[i];
y[i] = Y[i];
}
}
check(tot);
}
}
/*
1
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
*/