也是一个2-sat的题。。
然后注意这题是双向边,所以并查集搞搞就好了,TJ都不用写了
但是我这代码不知道为什么WA1了。。留坑。。
反正方法是这样了
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int N=10005*2;
const int M=10005;
int T;
int n,m;
struct qq
{
int x,y,last;
}e[M];
int rk[N];//这个点在回路里排第几
bool check(int u0,int v0,int u1,int v1)
{
if(u0==u1||u0==v1||v0==u1||v0==v1)return false;
u0=rk[u0];v0=rk[v0];
u1=rk[u1];v1=rk[v1];
if(u0>v0)swap(u0,v0);
if(u1>v1)swap(u1,v1);
if(v0<u1||v1<u0)return false;
return (u0<u1)==(v0<v1);
}
int f[N];
int find (int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
void init (int x,int y)
{
int fx=find(x),fy=find(y);
if (fx==fy) return ;
f[fx]=fy;
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
for (int u=1;u<=m;u++) scanf("%d%d",&e[u].x,&e[u].y);
for (int u=1;u<=n;u++)
{
int x;
scanf("%d",&x);
rk[x]=u;
}
if (m>3*n-6) {printf("NO");continue;}
for (int u=1;u<=2*m;u++) f[u]=u;
bool tf=true;
for (int u=1;u<=m;u++)
for (int i=u+1;i<=m;i++)
if (check(e[u].x,e[u].y,e[i].x,e[i].y))
{
int fx=find(u),fy=find(i);
if (fx==fy) tf=false;
init(u,i+m);
init(i,u+m);
}
if (tf) printf("YES\n");
else printf("NO\n");
}
return 0;
}