题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1997
题意:给定一个图和一个哈密顿回路,判定是否是平台图。
解法: 用平面图m<=3n-6的性质剪枝条
若两条边在圆内相交,则他们在圆外也是相交的,即若a,b不能同时取,a’,b’也不能同时取
按2-sat建模缩点后判断合法性
///BZOJ 1997 平面图判定
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int T, n, m, dfs_clk, top, scc, edgecnt;
int u[maxn], v[maxn], c[maxn], pos[maxn];
int head[maxn], dfn[maxn], low[maxn], s[maxn], belong[maxn];
bool inq[maxn];
struct edge{
int v,next;
}E[1000010];
void init(){
edgecnt=0;
memset(head, -1, sizeof(head));
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn));
memset(belong, 0, sizeof(belong));
dfs_clk=top=scc=0;
}
void addedge(int u, int v){
E[edgecnt].v = v, E[edgecnt].next = head[u], head[u] = edgecnt++;
}
void tarjan(int x){
int now=0;
dfn[x]=low[x]=++dfs_clk;
s[++top]=x; inq[x]=1;
for(int i=head[x];i+1;i=E[i].next){
int v=E[i].v;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(inq[v]){
low[x]=min(low[x],dfn[v]);
}
}
if(low[x]==dfn[x]){
scc++;
while(now!=x){
now=s[top]; top--;
belong[now]=scc;
inq[now]=0;
}
}
}
int main()
{
scanf("%d", &T);
while(T--){
scanf("%d%d", &n,&m);
for(int i=1; i<=m; i++) scanf("%d%d", &u[i],&v[i]);
init();
for(int i=1; i<=n; i++) scanf("%d", &c[i]);
if(m>3*n-6){
puts("NO");
continue;
}
for(int i=1; i<=n; i++) pos[c[i]]=i;
int cur=0;
for(int i=1; i<=m; i++){
u[i]=pos[u[i]];
v[i]=pos[v[i]];
if(u[i]>v[i]) swap(u[i],v[i]);
if(v[i]-u[i]==1||(v[i]==n&&u[i]==1)) continue;
u[++cur]=u[i], v[cur]=v[i];
}
cur=m;
for(int i=1; i<=m; i++){
for(int j=i+1; j<=m; j++){
if((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i])){
addedge(2*i-1,2*j);
addedge(2*i,2*j-1);
addedge(2*j-1,2*i);
addedge(2*j,2*i-1);
}
}
}
for(int i=1; i<=2*m; i++) if(!dfn[i]) tarjan(i);
bool flag = 1;
for(int i=1; i<=m; i++){
if(belong[i*2]==belong[i*2-1]){
flag = 0;
}
}
puts(flag?"YES":"NO");
}
return 0;
}