题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=1997
思路
平面图上的边要么在哈密顿回路内,要么在哈密顿回路外。每条边视为两个点,然后2-sat解决。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn=1200;
const int maxm=800000;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int pre[maxm+10],now[maxn+10],son[maxm+10],tot;
int t,n,m,u[maxn+10],v[maxn+10],c[maxn+10],cntm;
int dfn[maxn+10],low[maxn+10],cnt,cntl,top,stack[maxn+10];
int belong[maxn+10],instack[maxn+10],pos[maxn+10];
inline int ins(int a,int b)
{
pre[++tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int tarjan(int u)
{
dfn[u]=low[u]=++cnt;
stack[++top]=u;
instack[u]=1;
int j=now[u];
while(j)
{
int v=son[j];
if(!dfn[v])
{
tarjan(v);
low[u]=std::min(low[u],low[v]);
}
else if(instack[v])
{
low[u]=std::min(low[u],dfn[v]);
}
j=pre[j];
}
if(dfn[u]==low[u])
{
++cntl;
int w=0;
while(w!=u)
{
w=stack[top--];
belong[w]=cntl;
instack[w]=0;
}
}
return 0;
}
int main()
{
t=read();
while(t--)
{
memset(now,0,sizeof now);
memset(dfn,0,sizeof dfn);
memset(belong,0,sizeof belong);
cntm=cnt=cntl=tot=0;
n=read();
m=read();
for(int i=1; i<=m; ++i)
{
u[i]=read();
v[i]=read();
}
for(int i=1; i<=n; ++i)
{
c[i]=read();
}
if(m>3*n-6)
{
puts("NO");
continue;
}
for(int i=1; i<=n; ++i)
{
pos[c[i]]=i;
}
for(int i=1; i<=m; ++i)
{
u[i]=pos[u[i]];
v[i]=pos[v[i]];
if(u[i]>v[i])
{
std::swap(u[i],v[i]);
}
if((v[i]-u[i]==1)||((u[i]==1)&&(v[i]==n)))
{
continue;
}
u[++cntm]=u[i];
v[cntm]=v[i];
}
m=cntm;
for(int i=1; i<=m; ++i)
{
for(int j=1; j<i; ++j)
{
if(((u[i]<u[j])&&(v[i]<v[j])&&(v[i]>u[j]))
||((u[i]>u[j])&&(v[i]>v[j])&&(u[i]<v[j])))
{
ins(2*i-1,2*j);
ins(2*j,2*i-1);
ins(2*i,2*j-1);
ins(2*j-1,2*i);
}
}
}
for(int i=1; i<=2*m; ++i)
{
if(!dfn[i])
{
tarjan(i);
}
}
int flag=1;
for(int i=1; i<=m; ++i)
{
if(belong[2*i-1]==belong[2*i])
{
puts("NO");
flag=0;
break;
}
}
if(flag)
{
puts("YES");
}
}
return 0;
}