Description
若能将无向图G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称G是平面图。判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。
Solution
考虑把哈密顿路径画成一个圈,那么剩下的路径要么在圆外要么在圆内。问题变成求是否存在一种方案使得所有边不相交
这是一个很经典的2-SAT模型,对于两条相交的边分别连(i,j’)和(i’,j)然后tarjan即可
同时我们还需要知道一个结论,那就是若一个图m>3n-6则这个图一定不是平面图
这样暴力连边的复杂度就是十分科学的了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define fi first
#define se second
typedef std:: pair <int,int> pair;
const int N=1205;
const int E=N*N;
struct edge {int y,next;} e[E];
std:: stack<int> stack;
pair g[E];
int dfn[N],low[N],bel[N],id[N];
int ls[N],edCnt;
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}
void dfs(int now) {
dfn[now]=low[now]=++dfn[0];
stack.push(now); vis[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (!dfn[e[i].y]) {
dfs(e[i].y);
low[now]=std:: min(low[now],low[e[i].y]);
} else if (vis[e[i].y]) {
low[now]=std:: min(low[now],dfn[e[i].y]);
}
}
if (dfn[now]==low[now]) {
int y=0; bel[0]++;
while (y!=now) {
y=stack.top(); stack.pop();
bel[y]=bel[0]; vis[y]=0;
}
}
}
void tarjan(int n) {
fill(dfn,0); fill(low,0); bel[0]=0;
rep(i,1,n) if (!dfn[i]) dfs(i);
}
int main(void) {
for (int T=read();T--;) {
int n=read(),m=read();
rep(i,1,m) g[i]=pair(read(),read());
rep(i,1,n) id[read()]=i;
rep(i,1,m) g[i]=pair(id[g[i].fi],id[g[i].se]);
rep(i,1,m) g[i]=pair(std:: min(g[i].fi,g[i].se),std:: max(g[i].fi,g[i].se));
if (m>n*3-6) {
puts("NO"); continue;
}
fill(ls,0); edCnt=0;
rep(i,1,m) rep(j,i+1,m) {
if (g[i].fi<g[j].fi&&g[i].se>g[j].fi&&g[i].se<g[j].se) {
add_edge(i,j+m);
add_edge(j,i+m);
} else if (g[i].fi>g[j].fi&&g[i].fi<g[j].se&&g[i].se>g[j].se) {
add_edge(i,j+m);
add_edge(j,i+m);
}
}
tarjan(m*2);
bool flag=true;
rep(i,1,m) if (bel[i]==bel[i+m]) {
flag=false; break;
}
if (flag) puts("YES");
else puts("NO");
}
return 0;
}