1. 程式人生 > >bzoj1997: [Hnoi2010]Planar

bzoj1997: [Hnoi2010]Planar

false family sta nbsp iostream using n) style main

把回路的邊想像成一個環,對於不在此上的邊,有兩種畫法:在環內或環外

這就構成了2-sat二選一的要求。YY一下,容易想到構圖。

然而狀態很差寫得很慢

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    int x,y,next;
}a[2100000];int len,last[21000
]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int z,dfn[21000],low[21000]; int top,sta[21000];bool v[21000]; int cnt,bel[21000]; void SCC(int x) { dfn[x]=low[x]=++z; sta[++top]=x;v[x]=true; for(int k=last[x];k;k=a[k].next) {
int y=a[k].y; if(dfn[y]==0) { SCC(y); low[x]=min(low[x],low[y]); } else if(v[y]==true) low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]) { int k;cnt++; do { k=sta[top];top--; v[k]
=false; bel[k]=cnt; }while(k!=x); } } struct edge{int x,y;}e[21000]; int pos[21000]; int main() { int T; scanf("%d",&T); while(T--) { int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d",&e[i].x,&e[i].y); for(int i=1;i<=n;i++) scanf("%d",&x),pos[x]=i; if(m>3*n-6){printf("NO\n");continue;} int tp=0; for(int i=1;i<=m;i++) { e[i].x=pos[e[i].x];e[i].y=pos[e[i].y]; if(e[i].x>e[i].y)swap(e[i].x,e[i].y); if(e[i].y-e[i].x==1||(e[i].y==n&&e[i].x==1))continue; e[++tp].x=e[i].x,e[tp].y=e[i].y; } m=tp; len=0;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) for(int j=i+1;j<=m;j++) if( (e[i].x<e[j].x&&e[j].x<e[i].y&&e[i].y<e[j].y) || (e[j].x<e[i].x&&e[i].x<e[j].y&&e[j].y<e[i].y)) { ins(i,j+m); ins(i+m,j); ins(j,i+m); ins(j+m,i); } z=top=cnt=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(v,false,sizeof(v)); for(int i=1;i<=2*m;i++) if(dfn[i]==0)SCC(i); bool bk=true; for(int i=1;i<=m;i++) if(bel[i]==bel[i+m]){bk=false;break;} if(bk)printf("YES\n"); else printf("NO\n"); } return 0; }

bzoj1997: [Hnoi2010]Planar