#2-SAT,平面圖#洛谷 3209 [HNOI2010] 平面圖判定
阿新 • • 發佈:2021-11-18
2-SAT,平面圖
分析
首先一張圖是平面圖的必要條件為 \(m\leq 3*n-6\),
然後考慮到這題的圖存在哈密爾頓迴路,也就是說非環邊因為跨立形成奇環即為無解
那麼直接拆點跑2-SAT就可以了
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int N=1211; struct node{int y,next;}e[N*N]; int dfn[N],low[N],v[N],stac[N],col[N],rk[N],as[N]; int et,flag,tot,Top,cnt,n,m,X[N*10],Y[N*10]; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline signed min(int a,int b){return a<b?a:b;} inline void tarjan(int x){ dfn[x]=low[x]=++tot,v[x]=1,stac[++Top]=x; for (rr int i=as[x];i;i=e[i].next) if (!dfn[e[i].y]){ tarjan(e[i].y); low[x]=min(low[x],low[e[i].y]); }else if (v[e[i].y]) low[x]=min(low[x],dfn[e[i].y]); if (dfn[x]==low[x]){ rr int y; ++cnt; do{ y=stac[Top--],v[y]=0, col[y]=cnt; }while (y!=x); } } inline void add(int x,int y){e[++et]=(node){y,as[x]},as[x]=et;} signed main(){ for (rr int T=iut();T;--T){ n=iut(),m=iut(),flag=et=1,tot=0; for (rr int i=1;i<=m;++i) X[i]=iut(),Y[i]=iut(); for (rr int i=1;i<=n;++i) rk[iut()]=i; if (m>3*n-6) {puts("NO"); continue;} for (rr int i=1;i<=m;++i){ X[i]=rk[X[i]],Y[i]=rk[Y[i]]; if (X[i]>Y[i]) X[i]^=Y[i],Y[i]^=X[i],X[i]^=Y[i]; if (X[i]+1==Y[i]||(X[i]==1&&Y[i]==n)) v[i]=1; } for (rr int i=1;i<m;++i) if (!v[i]) for (rr int j=i+1;j<=m;++j) if (!v[j]) if ((X[i]<X[j]&&X[j]<Y[i]&&Y[i]<Y[j])||(X[j]<X[i]&&X[i]<Y[j]&&Y[j]<Y[i])) add(i,j+m),add(i+m,j),add(j,i+m),add(j+m,i); for (rr int i=1;i<=m;++i) v[i]=0; for (rr int i=1;i<=m*2;++i) if (!dfn[i]) tarjan(i); for (rr int i=1;i<=m;++i) if (col[i]==col[i+m]) {puts("NO"),flag=0; break;} if (flag) puts("YES"); for (rr int i=1;i<=m*2;++i) as[i]=col[i]=dfn[i]=low[i]=0; } return 0; }