题目大意:
给定一个带有哈密顿回路的图,求此图是否为平面图。
思路:
既然有哈密顿回路,则可以把环外和环内看成两个不同的区域,然后如果有不是环上的边相交的话就不能同时在环内或者环外。然后就可以转化为2-SAT模型。
但是发现如果枚举去连边的话显然很可能会TLE。这个时候要用到平面图的一个定理,即任意一个平面图的边的个数不大于3*n-6,至于证明我就不知道了。。
然后就直接枚举连边跑2-SAT就好了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define pii pair<int,int>
#define fi first
#define se second
#define mk make_pair
typedef long long ll;
using namespace std;
void File(){
freopen("bzoj1997.in","r",stdin);
freopen("bzoj1997.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=200+10;
const int maxm=1e4+10;
int T,n,m,a[maxn],pos[maxn];
pii E[maxm];
vector<int>G[maxn*6];
void init(){
read(n); read(m);
int u,v;
REP(i,1,m)read(u),read(v),E[i]=mk(u,v);
REP(i,1,n)read(a[i]),pos[a[i]]=i;
REP(i,1,m){
E[i].fi=pos[E[i].fi]; E[i].se=pos[E[i].se];
if(E[i].fi>E[i].se)swap(E[i].fi,E[i].se);
//cout<<E[i].fi<<" "<<E[i].se<<endl;
}
}
void build_map(){
REP(i,1,m*2)G[i].clear();
REP(i,1,m)REP(j,i+1,m){
if(E[i].fi<=E[j].fi && E[i].se>=E[j].se)continue;
if(E[i].fi>=E[j].fi && E[i].se<=E[j].se)continue;
if(E[i].se<=E[j].fi || E[j].se<=E[i].fi)continue;
//cout<<i<<" "<<j<<endl;//" "<<E[i].fi<<" "<<E[i].se<<" "<<E[j].fi<<" "<<E[j].se<<endl;
G[i].push_back(j+m);
G[j].push_back(i+m);
G[i+m].push_back(j);
G[j+m].push_back(i);
//cout<<i<<" "<<j+m<<endl;
//cout<<j<<" "<<i+m<<endl;
}
//cout<<"--------------------"<<endl;
}
int low[maxm*6],dfn[maxm*6],cnt_dfn,cnt_scc,bel[maxm*6];
stack<int>stk;
void tarjan(int u){
low[u]=dfn[u]=++cnt_dfn;
stk.push(u);
for(int sz=G[u].size()-1,i=0;i<=sz;++i){
int v=G[u][i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!bel[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++cnt_scc;
for(int p=0;p!=u;stk.pop()){
p=stk.top();
//cout<<p<<" ";
bel[p]=cnt_scc;
}
//cout<<endl;
}
}
bool work(){
cnt_dfn=cnt_scc=0;
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(bel,0,sizeof(bel));
REP(i,1,m*2)if(!dfn[i])
tarjan(i);
REP(i,1,m)if(bel[i]==bel[i+m])
return false;
return true;
}
int main(){
File();
read(T);
while(T--){
init();
if(m>3*n-6){
puts("NO");
continue;
}
build_map();
work() ? puts("YES") : puts("NO");
}
return 0;
}