天天看點

【BZOJ】1997: [Hnoi2010]Planar - 2-SAT & 平面圖結論

傳送門: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;
}
           

繼續閱讀