P3209 [HNOI2010]平面图判定

题意

题目描述

若能将无向图\(G=(V,E)\)画在平面上使得任意两条无重合顶点的边不相交,则称\(G\)是平面图。判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。

输入输出格式

输入格式:

输入文件的第一行是一个正整数\(T\),表示数据组数 (每组数据描述一个需要判定的图)。接下来从输入文件第二行开始有\(T\)组数据,每组数据的第一行是用空格隔开的两个正整数\(N\)和\(M\),分别表示对应图的顶点数和边数。紧接着的\(M\)行,每行是用空格隔开的两个正整数\(u\)和\(v\left(1\leq u,v\leq N\right)\),表示对应图的一条边\(\left(u,v\right)\), 输入的数据保证所有边仅出现一次。每组数据的最后一行是用空格隔开的\(N\)个正整数,从左到右表示对应图中的一个哈密顿回路\(V_1,V_2,\dots ,V_N\),即对任意\(i\not=j\)有\(V_i\not=V_j\)且对任意\(1\leq i\leq N-1\)有\(\left(V_i,V_i-1\right)\in E\)及\(\left(V_1,V_N\right)\in E\)。输入的数据保证\(100\%\)的数据满足\(T\leq100,3\leq N\leq200,M\leq1000\)。

输出格式:

包含\(T\)行,若输入文件的第\(i\)组数据所对应图是平面图,则在第\(i\)行输出 \(\text{YES}\),否则在第\(i\)行输出\(\text{NO}\),注意均为大写字母。

输入输出样例

输入样例#1:

2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5

输出样例#1:

NO
YES

思路

这题毒瘤,要先转对偶图... --huyufeifei

其实这题也没那么毒瘤,直接\(2-SAT\)或者并查集就好了。

我们先把哈密顿回路搬出来,画成一个圆,再来考虑图上其他的边。其他的边有两种画法:画在圆内,画在圆外。有些边,如果都画在圆内,就会相交,不符合平面图的性质;而如果他们都画在圆外,也会相交。所以我们可以把边拿出来,把其是否画在圆内作为这条边的边权,两条边不可相交作为其限制条件,做\(2-SAT\)就好了。当然,\(alec\)神仙写的是并查集做法,也是十分可行的。

还有一个剪枝:显然平面图中的边的数量不能太多,因为图越稠密越难画出平面图,所以当当前状况下边数过多时,我们就可以直接判NO。上网查资料得\(m\leq 3n-2\)(这个是可以用欧拉公式证明的。 --logeadd),加上剪枝就能跑得很快了。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=205;
const int MAXM=605;
int T,n,m,id[MAXN],inv[MAXN],u[10005],v[10005];
int nn,U[MAXM],V[MAXM];
int cnt,top[MAXM<<1],to[(MAXM*MAXM)<<2],nex[(MAXM*MAXM)<<2];
int tot,js,dfn[MAXM<<1],low[MAXM<<1],bel[MAXM<<1];
bool cir[MAXN][MAXN],vis[MAXM<<1];
stack<int>S;
int read()
{
int re=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
void add_edge(int x,int y){to[++cnt]=y,nex[cnt]=top[x],top[x]=cnt;}
void tarjan(int now)
{
dfn[now]=low[now]=++tot,vis[now]=true,S.push(now);
for(int i=top[now];i;i=nex[i])
if(!dfn[to[i]]) tarjan(to[i]),low[now]=min(low[now],low[to[i]]);
else if(vis[to[i]]) low[now]=min(low[now],low[to[i]]);
if(dfn[now]==low[now])
{
bel[now]=++js,vis[now]=false;
while(S.top()!=now) bel[S.top()]=js,vis[S.top()]=false,S.pop();
S.pop();
}
}
int main()
{
T=read();
while(T--)
{
n=read(),m=read(),nn=cnt=tot=js=0;
memset(id,0,sizeof id);
memset(inv,0,sizeof inv);
memset(u,0,sizeof u);
memset(v,0,sizeof v);
memset(U,0,sizeof U);
memset(V,0,sizeof V);
memset(top,0,sizeof top);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(bel,0,sizeof bel);
memset(cir,false,sizeof cir);
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
if(x>y) swap(x,y);
u[i]=x,v[i]=y;
}
for(int i=1;i<=n;i++)
{
int x=read();
id[x]=i,inv[i]=x;
if(i!=1)
{
int y=inv[i-1];
if(x>y) swap(x,y);
cir[x][y]=true;
}
}
if(m>3*n-6)
{
puts("NO");
continue;
}
if(inv[1]<inv[n]) cir[inv[1]][inv[n]]=true;
else cir[inv[n]][inv[1]]=true;
for(int i=1;i<=m;i++) if(!cir[u[i]][v[i]]) U[++nn]=u[i],V[nn]=v[i];
for(int i=1;i<=nn;i++)
for(int j=i+1;j<=nn;j++)
{
int x=id[U[i]],y=id[V[i]],xx=id[U[j]],yy=id[V[j]];
if(x>y) swap(x,y);
if(xx>yy) swap(xx,yy);
if((x<xx&&xx<y&&y<yy)||(xx<x&&x<yy&&yy<y)) add_edge(i,j+nn),add_edge(i+nn,j),add_edge(j,i+nn),add_edge(j+nn,i);
}
for(int i=1;i<=(nn<<1);i++) if(!dfn[i]) tarjan(i);
bool ans=true;
for(int i=1;i<=nn;i++)
if(bel[i]==bel[i+nn])
{
ans=false;
break;
}
if(ans) puts("YES");
else puts("NO");
}
return 0;
}

Luogu P3209 [HNOI2010]平面图判定(2-SAT)的更多相关文章

  1. P3209 [HNOI2010]平面图判定

    P3209 [HNOI2010]平面图判定 哈密尔顿环之外的任意一条边,要么连在环内部,要么连在环外部 判断两条边在同一部分会相交,则这两条边必须分开 那么把边看作点连边,跑二分图染色就行 #incl ...

  2. 洛谷 P3209 [HNOI2010] 平面图判定

    链接: P3209 题意: 给出 \(T\) 张无向图 \((T\leq100)\),并给出它对应的哈密顿回路,判断每张图是否是平面图. 分析: 平面图判定问题貌似是有线性做法的,这里给出链接,不是本 ...

  3. 洛谷P3209 [HNOI2010]平面图判定(2-SAT)

    传送门 看到哈密顿回路就被吓傻了……结果没有好好考虑性质…… 首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass 然后考虑原图,先把哈密顿回路单独摘出来,就是 ...

  4. bzoj1997 [HNOI2010]平面图判定Plana

    bzoj1997 [HNOI2010]平面图判定Planar 链接 bzoj luogu 思路 好像有很多种方法过去.我只说2-sat 环上的边,要不在里面,要不在外边. 有的边是不能同时在里面的,可 ...

  5. [BZOJ1997][HNOI2010] 平面图判定

    Description Input Output     是的..BZOJ样例都没给.     题解(from 出题人): 如果只考虑简单的平面图判定,这个问题是非常不好做的. 但是题目中有一个条件— ...

  6. [HNOI2010]平面图判定

    Description: 若能将无向图 \(G=(V, E)\) 画在平面上使得任意两条无重合顶点的边不相交,则称 \(G\) 是平面图.判定一个图是否为平面图的问题是图论中的一个重要问题.现在假设你 ...

  7. Luogu3209 HNOI2010 平面图判定 平面图、并查集

    传送门 题意:$T$组数据,每组数据给出一个$N$个点,$M$条边,并存在一个$N$元环的图,试判断其是否为一个可平面图(如果存在一种画法,使得该图与给出的图同构且边除了在顶点处以外互相不相交,则称其 ...

  8. [HNOI2010] 平面图判定 planar

    标签:二分图判定.题解: 首先可以把题目中给你的那个环给画出来,这样就可以发现对于任意一个图来说,如果两条边要相交,就不能让他们相交,那么这两条边就要一条在里面一条在外面,如果把环画成一条链,那么就是 ...

  9. BZOJ1997 HNOI2010 平面图判定 planar (并查集判二分图)

    题意 判断一个存在哈密顿回路的图是否是平面图. n≤200,m≤10000n\le200,m\le10000n≤200,m≤10000 题解 如果一定存在一个环,那么连的边要么在环里面要么在外面.那么 ...

随机推荐

  1. 异或+桶——cf768C

    有个结论是到最后肯定出现循环节..感觉这种做法有点歪 正解当然是题解啦 虽然到了1e8,但是cf上还是能过的 #include<bits/stdc++.h> #define rep(i,s ...

  2. nginx css,js合并插件,淘宝nginx合并js,css插件

    先下载Nginx_concat_module,下载后把它放在/usr/local/src/文件夹中,新建文件夹nginx-http-concat把下载的config  ngx_http_concat_ ...

  3. hdu多校第四场1001 (hdu6614) AND Minimum Spanning Tree 签到

    题意: 一个完全图,某两点边权为这两点编号之按位与,求最小生成树,输出字典序最小的. 题解: 如果点数不为$2^n-1$,则每一点均可找到一点,两点之间边权为0,只需找到该点二进制下其最左边的0是第几 ...

  4. EXCEL函数常用技巧浅析

    EXCEL函数常用技巧浅析 EXCEL函数是一门趣味性非常大的游戏,此贴内容基本上为总结前人经验而来.废话不多说,我们现在走入正题. 一:判断数值奇偶性 1.1  ISODD(number) 判断一个 ...

  5. 区间dp及优化

    看了下感觉区间dp就是一种套路,直接上的板子代码就好了. 基础题ac代码:石子归并 #include<bits/stdc++.h> using namespace std; typedef ...

  6. vue之样式问题

    在样式开发过程中,有两个问题比较突出: 全局污染 —— CSS 文件中的选择器是全局生效的,不同文件中的同名选择器,根据 build 后生成文件中的先后顺序,后面的样式会将前面的覆盖: 选择器复杂 — ...

  7. 使用APOC技术从MYSQL数据库导数据到Neo4j图数据库(JDBC)

                                                     Neo4j 数据导入 一.安装与部署Neo4j 直接在官网下载安装包安装,解压即可. 2.mysql ...

  8. Nodejs之路(四)—— MongoDB&MySQL

    一.MongoDB 1.1概述 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.MongoDB 是一个介于关系数据库和非 ...

  9. iOS开发系列-文件上传

    概述 Http协议对文件上传协议要求的 1. 必须设置请求头Content-Type为multipart/form-data.在iOS中后面需要跟上分隔符比如:boundary=----WebKitF ...

  10. /bin /usr/bin /sbin /usr/sbin 目录的作用

    /bin是系统的一些指令.bin为binary的简写主要放置一些系统的必备执行档例如:cat.cp.chmod df.dmesg.gzip.kill.ls.mkdir.more.mount.rm.su ...