BZOJ 1997 [Hnoi2010]Planar - 2-sat
2017-10-20 19:51
435 查看
由欧拉公式:n-m+r=2,n个顶点,m条边,r个面
对于简单极大平面图,3r=2m (每个面由3条边组成,一边被2个面共享)
代入得 m=3n-6
通过m<=3n-6减枝,将m控制在1000以内。
平面图,即没有线段交叉,而此题已经给出了一个环,于是每一条非环上的线段只有两种情况,一是在环外,二是在环内,若有两线段相交则不为平面图。
确定两个线段的关系,若其坐标交叉,则必然不能同时取外或取内,由于只有两个状态,正好类比于2-sat中两个状态。强制要求一个取外时另一个必须取内,加上约束跑一个tarjan即可。
网上那个判线段相交的方法都是什么鬼啊,竟然还出奇地雷同。对于跨越n~1的线段,很明显要特判一下。。。还好数据弱(雾)
对于简单极大平面图,3r=2m (每个面由3条边组成,一边被2个面共享)
代入得 m=3n-6
通过m<=3n-6减枝,将m控制在1000以内。
平面图,即没有线段交叉,而此题已经给出了一个环,于是每一条非环上的线段只有两种情况,一是在环外,二是在环内,若有两线段相交则不为平面图。
确定两个线段的关系,若其坐标交叉,则必然不能同时取外或取内,由于只有两个状态,正好类比于2-sat中两个状态。强制要求一个取外时另一个必须取内,加上约束跑一个tarjan即可。
网上那个判线段相交的方法都是什么鬼啊,竟然还出奇地雷同。对于跨越n~1的线段,很明显要特判一下。。。还好数据弱(雾)
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> using namespace std; const int maxn=20005; const int maxm=1000005; struct edge { int to,next; }e[maxm]; int cnt,n,m,T,scnt,scccnt,dfs_clock,ecnt; int stack[maxn],dfn[maxn],low[maxn],head[maxn],belong[maxn],x[maxm],y[maxm],Nr[maxm]; bool inq[maxn]; int read() { int x=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar(); return x; } void insert(int a,int b) { e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt; } void tarjan(int u) { dfn[u]=low[u]=++dfs_clock; inq[u]=true; stack[++scnt]=u; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]); else if(inq[v])low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scccnt++; int now=-1; while(now!=u) { now=stack[scnt--]; inq[now]=false; belong[now]=scccnt; } } } bool cross(int i,int j) { return ((x[j]-x[i])*(x[j]-y[i])>0&&(y[j]-y[i])*(y[j]-x[i])<0) ||((x[j]-x[i])*(x[j]-y[i])<0&&(y[j]-y[i])*(y[j]-x[i])>0); } int main() { scanf("%d",&T); while(T--) { scccnt=dfs_clock=cnt=ecnt=0; memset(head,0,sizeof head); memset(dfn,0,sizeof dfn); memset(low,0,sizeof low); n=read(),m=read(); for(int i=1;i<=m;i++) x[i]=read(),y[i]=read(); for(int i=1,t;i<=n;i++) t=read(), Nr[t]=i; if(m>3*n-6) { puts("NO"); continue; } for(int i=1;i<=m;i++) { x[i]=Nr[x[i]]; y[i]=Nr[y[i]]; if(x[i]>y[i])swap(x[i],y[i]); if(y[i]-x[i]==1||(x[i]==1&&y[i]==n)) continue; x[++ecnt]=x[i]; y[ecnt]=y[i]; } for(int i=1;i<=ecnt;i++) for(int j=i+1;j<=ecnt;j++) { if(cross(i,j)) { insert((i<<1),(j<<1)^1); insert((i<<1)^1,(j<<1)); insert((j<<1),(i<<1)^1); insert((j<<1)^1,(i<<1)); } } for(int i=2;i<=2*ecnt+1;i++) if(!dfn[i])tarjan(i); bool ok=true; for(int i=1;i<=ecnt;i++) if(belong[i<<1]==belong[(i<<1)+1]) { ok=false; break; } puts(ok?"YES":"NO"); } }
相关文章推荐
- 【BZOJ1997】[Hnoi2010]Planar【平面图判定】【2-SAT】
- BZOJ 1997 HNOI 2010 Planar 2-SAT
- [BZOJ1997][Hnoi2010]Planar(2-SAT)
- BZOJ 1997: [Hnoi2010]Planar [2-SAT]
- [bzoj1997][Hnoi2010]Planar 2-sat
- bzoj1997[Hnoi2010]Planar 2-SAT
- [bzoj1997][Hnoi2010]Planar(2-sat||括号序列)
- BZOJ 1997: [Hnoi2010]Planar|2-SAT|二分图染色
- [BZOJ1997][HNOI2010][2-sat]Planar
- 【平面图判定+2-SAT验证】BZOJ1997 [Hnoi2010]Planar
- BZOJ.1997.[HNOI2010]Planar(2-SAT)
- BZOJ 1997 Hnoi2010 Planar 2-sat
- BZOJ 1997 HNOI 2010 Planar 2-SAT
- 【2-SAT(tarjan)】BZOJ1997-[Hnoi2010]Planar
- bzoj 1997: [Hnoi2010]Planar (2-SAT)
- BZOJ 1997: [Hnoi2010]Planar 2-sat
- 【BZOJ1997】[Hnoi2010]Planar 2-SAT
- bzoj 1997: [Hnoi2010]Planar 2-SAT+平面图
- [BZOJ1997][Hnoi2010]Planar(2-SAT)
- [BZOJ1997][HNOI2010]Planar(2-SAT)