Luogu P3209 [HNOI2010]平面图判定(2-SAT)
题意
题目描述
若能将无向图\(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)的更多相关文章
- P3209 [HNOI2010]平面图判定
P3209 [HNOI2010]平面图判定 哈密尔顿环之外的任意一条边,要么连在环内部,要么连在环外部 判断两条边在同一部分会相交,则这两条边必须分开 那么把边看作点连边,跑二分图染色就行 #incl ...
- 洛谷 P3209 [HNOI2010] 平面图判定
链接: P3209 题意: 给出 \(T\) 张无向图 \((T\leq100)\),并给出它对应的哈密顿回路,判断每张图是否是平面图. 分析: 平面图判定问题貌似是有线性做法的,这里给出链接,不是本 ...
- 洛谷P3209 [HNOI2010]平面图判定(2-SAT)
传送门 看到哈密顿回路就被吓傻了……结果没有好好考虑性质…… 首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass 然后考虑原图,先把哈密顿回路单独摘出来,就是 ...
- bzoj1997 [HNOI2010]平面图判定Plana
bzoj1997 [HNOI2010]平面图判定Planar 链接 bzoj luogu 思路 好像有很多种方法过去.我只说2-sat 环上的边,要不在里面,要不在外边. 有的边是不能同时在里面的,可 ...
- [BZOJ1997][HNOI2010] 平面图判定
Description Input Output 是的..BZOJ样例都没给. 题解(from 出题人): 如果只考虑简单的平面图判定,这个问题是非常不好做的. 但是题目中有一个条件— ...
- [HNOI2010]平面图判定
Description: 若能将无向图 \(G=(V, E)\) 画在平面上使得任意两条无重合顶点的边不相交,则称 \(G\) 是平面图.判定一个图是否为平面图的问题是图论中的一个重要问题.现在假设你 ...
- Luogu3209 HNOI2010 平面图判定 平面图、并查集
传送门 题意:$T$组数据,每组数据给出一个$N$个点,$M$条边,并存在一个$N$元环的图,试判断其是否为一个可平面图(如果存在一种画法,使得该图与给出的图同构且边除了在顶点处以外互相不相交,则称其 ...
- [HNOI2010] 平面图判定 planar
标签:二分图判定.题解: 首先可以把题目中给你的那个环给画出来,这样就可以发现对于任意一个图来说,如果两条边要相交,就不能让他们相交,那么这两条边就要一条在里面一条在外面,如果把环画成一条链,那么就是 ...
- BZOJ1997 HNOI2010 平面图判定 planar (并查集判二分图)
题意 判断一个存在哈密顿回路的图是否是平面图. n≤200,m≤10000n\le200,m\le10000n≤200,m≤10000 题解 如果一定存在一个环,那么连的边要么在环里面要么在外面.那么 ...
随机推荐
- H5 回到顶部按钮
//这里我用的是svg,所以代码老长了,可以把svg部分换成自己的图片什么的$(function(){ var obj = $('<div style="width:1.3rem;po ...
- 牛客多校第四场 I string 后缀自动机/回文自动机
这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅! 题意: 求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个. 题解: 要注意的是,一般字符串题中的“ ...
- Linux课程---15、域名相关
Linux课程---15.域名相关 一.总结 一句话总结: 先购买域名,再备案,再解析,域名即可使用 1.域名备案是怎么回事(比如二级域名,三级域名)? 每个二级域名需要备案一次,三级域名不需要备案, ...
- Redis-GEO
一. Redis的GEO特性 Redis3.2版本提供了GEO功能,支持存储地理位置信息用来实现诸如摇一摇,附近位置这类依赖于地理位置信息的功能.二. 命令2.1 增加地理位置信息 命令:geoadd ...
- System.Web.Mvc.IController.cs
ylbtech-System.Web.Mvc.IController.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, Public ...
- uoj#370【UR #17】滑稽树上滑稽果
题目 低智选手果然刷不动uoj 首先考虑一下构造一棵树显然是骗你玩的,按位与这个东西越做越小,挂到链的最下面显然不会劣于挂到之前的某一个点下面,所以我们只需要求一个排列使得答案最小就好了 设\(A=\ ...
- C开发系列-字符串
C语言字符串 C语言字符串本质是使用字符数组来存储的. #include <stdio.h> int main() { "jake"; // "jake&qu ...
- linux /bin/find 报错:paths must precede expression 及find应用
1.问题描述,运行下面的命令,清楚日志 [resin@xx ~]$ ssh xxx "/usr/bin/find /data/logs/`dirname st_qu/stdout.log` ...
- Python全栈开发:web框架
Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 ...
- 用在 AMD64 上 aria2_1.33.1-1_amd64.deb 的下载页面
用在 AMD64 上 aria2_1.33.1-1_amd64.deb 的下载页面 如果您正在运行 Ubuntu,请尽量使用像 aptitude 或者 synaptic 一样的软件包管理器,代替人工手 ...