传送门:bzoj1997
读题…
题解
把哈密顿回路看成一个环,圆上相交的两条弧不能在同一侧(圆内/外)
O ( m 2 ) O(m^2) O(m2)过不了,但存在结论:
v ≥ 3 v\geq 3 v≥3的平面图 e ≤ 3 v − 6 e\leq 3v-6 e≤3v−6
把 m > 3 n − 6 m>3n-6 m>3n−6的判掉就过了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1200,M=8e5+10;
int tk,tp,n,m,a[N],b[N],pos[N];
int dfn,df[N],low[N],bel[N],cir,stk[N],top;
int head[N],to[M],nxt[M],tot;
void init(int n)
{
int sz=(n+1)<<2;
memset(head,0,sz);tot=0;
memset(df,0,sz);memset(bel,0,sz);
dfn=cir=top=0;
}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
void tar(int x)
{
int i,j,res;df[x]=low[x]=++dfn;stk[++top]=x;
for(i=head[x];i;i=nxt[i]){
j=to[i];
if(!df[j]){
tar(j);low[x]=min(low[x],low[j]);
}else if(!bel[j]) low[x]=min(low[x],df[j]);
}
if(low[x]==df[x]){
for(cir++;;){
res=stk[top--];bel[res]=cir;
if(res==x) break;
}
}
}
int main(){
int i,j,x,y,ix,iy;
for(scanf("%d",&tk);tk;--tk){
scanf("%d%d",&n,&m);tp=0;
for(i=1;i<=m;++i) scanf("%d%d",&a[i],&b[i]);
for(i=1;i<=n;++i) {scanf("%d",&j);pos[j]=i;}
if(m>3*n-6) {puts("NO");continue;}
for(i=1;i<=m;++i){
a[i]=pos[a[i]];b[i]=pos[b[i]];
if(a[i]>b[i]) swap(a[i],b[i]);
if(a[i]+1<b[i]){a[++tp]=a[i];b[tp]=b[i];}
}
m=tp;tp=m<<1;init(tp);
for(i=1;i<=m;++i){
x=a[i];y=b[i];
for(j=i+1;j<=m;++j){
ix=a[j];iy=b[j];
if((x<iy && x>ix && y>iy)||(x<ix && y>ix && y<iy))
lk(i,j+m),lk(j+m,i),lk(i+m,j),lk(j,i+m);
}
}
for(i=1;i<=tp;++i) if(!df[i]) tar(i);
for(i=1;i<=m;++i) if(bel[i]==bel[i+m]) break;
puts(i<=m?"NO":"YES");
}
return 0;
}