P3209-平面图判定
平面图
平面图就是所有点的连边不相交的图。(当然是在你尽量想让它不相交的情况下)。这一点可以大概理解成拓扑图的性质,即每连一条边就会将某个区域进行分割——很明显,如果两个点分别处在两个不可达的区域,它们要连边显然是要穿过其他边的。
平面图定理
边数大于点数的三倍减六的图一定不是平面图。即设n为点数,m为边数,有
\]
关于平面图的其他定理和上定理的证明我不会不过我有大佬博客就不乱搬了。
关于此题题解
首先,它给出了n和m,我们先通过平面图定理判断一下,这样可以偷很多的懒。
然后,我们发现这个题是给了哈密顿回路的。那么我们就可以把这个图伸展成一个环便于理解。
然后,我们发现了这个图的性质——哈密顿回路相当于分割整个平面成了两个区域。也就是说,两个非哈密顿回路上的边的边顶多能共存两组。(因为不能交叉)
两个区域?共存两组?
2-SAT浮现出水面。对,我们可以给非哈密顿回路边的边连边,然后求它们的最大匹配。
(如果没有哈密顿回路这玩意还是个DPC问题)
2-SAT的模板我就不注释了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=3e4+5,maxv=205,maxm=2e6+5;
int cnt,Cir[maxv],rec[maxn],x1[maxn],y1[maxn],x2[maxn],y2[maxn];
//Cir用来按编号从小到大记录环,rec反向记录Cir;
//x1,y1,x2,y2分别记录全部边和去除环上边的剩余边
int tot,dfn[maxn],low[maxn],_n;
//tarjan用
int ecnt,head[maxm],nxt[maxm],to[maxm],belong[maxn];
//前向星用
bool cir[maxv][maxv];
//cir记录Cir
inline void addedge(int from,int too)
{
to[++ecnt]=too,nxt[ecnt]=head[from],head[from]=ecnt;
}
int st[maxn],top;
bool vis[maxn];
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
st[++top]=x;vis[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int u=to[i];
if(!dfn[u]){
tarjan(u);
low[x]=min(low[x],low[u]);
}else if(vis[x]){
low[x]=min(low[x],dfn[u]);
}
}
if (dfn[x] == low[x]) {
int v; belong[x] = ++_n;vis[x]=0;
while (v = st[top--], v != x) belong[v] = _n,vis[v]=0;
}
}
inline bool check()
{
for(int i=1;i<=(cnt<<1);i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=cnt;i++)
if(belong[i]==belong[i+cnt])return false;
return true;
}
inline void work()
{
int T,n,m;
n=read(),m=read();
memset(head,0,sizeof head);
memset(x1,0,sizeof x1);
memset(y1,0,sizeof y1);
memset(x2,0,sizeof x2);
memset(y2,0,sizeof y2);
memset(belong,0,sizeof belong);
memset(rec,0,sizeof rec);
memset(cir,0,sizeof cir);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(to,0,sizeof to);
memset(nxt,0,sizeof nxt);
memset(vis,0,sizeof vis);
memset(st,0,sizeof st);
ecnt=tot=cnt=_n=top=0;
for(int i=1;i<=m;i++)
{
x1[i]=read(),y1[i]=read();
if(x1[i]>y1[i]) swap(x1[i],y1[i]);
}//记录下来等会处理
rec[Cir[1]=read()]=1;
for(int i=2;i<=n;i++){
rec[Cir[i]=read()]=i;
(Cir[i]>Cir[i-1]?cir[Cir[i-1]][Cir[i]]:cir[Cir[i]][Cir[i-1]])=1;
}
(Cir[1]>Cir[n]?cir[Cir[n]][Cir[1]]:cir[Cir[1]][Cir[n]])=1;
//获取cir和rec
if(m>3*n-6){
printf("NO\n");return;
}
for(int i=1;i<=m;i++)
{
if(cir[x1[i]][y1[i]])continue;
x2[++cnt]=x1[i],y2[cnt]=y1[i];
}
for(int i=1;i<cnt;i++)
for(int j=i+1;j<=cnt;j++)
{
int a=rec[x2[i]] , b=rec[y2[i]] , x=rec[x2[j]] , y=rec[y2[j]];
if(a>b)swap(a,b);if(x>y)swap(x,y);
if((a<x and b>x and y>b) or (x<a and y>a and b>y))
addedge(i,j+cnt),addedge(j,i+cnt),addedge(i+cnt,j),addedge(j+cnt,i);
}
if(check())printf("YES\n");
else printf("NO\n");
}
}
int main()
{
int T=read();
while(T--) star::work();
return 0;
}
P3209-平面图判定的更多相关文章
- 洛谷P3209平面图判定 [HNOI2010] 2-sat
正解:2-sat(并茶几/强连通分量 解题报告: 传送门w 难受死了,连WA5次,正确率又-=INF了QAQ 然后先说下这题怎么做再来吐槽自己QAQ 首先这题其实和NOIp2010的关押罪犯挺像的,然 ...
- P3209 [HNOI2010]平面图判定
P3209 [HNOI2010]平面图判定 哈密尔顿环之外的任意一条边,要么连在环内部,要么连在环外部 判断两条边在同一部分会相交,则这两条边必须分开 那么把边看作点连边,跑二分图染色就行 #incl ...
- Luogu P3209 [HNOI2010]平面图判定(2-SAT)
P3209 [HNOI2010]平面图判定 题意 题目描述 若能将无向图\(G=(V,E)\)画在平面上使得任意两条无重合顶点的边不相交,则称\(G\)是平面图.判定一个图是否为平面图的问题是图论中的 ...
- [BZOJ1997][HNOI2010] 平面图判定
Description Input Output 是的..BZOJ样例都没给. 题解(from 出题人): 如果只考虑简单的平面图判定,这个问题是非常不好做的. 但是题目中有一个条件— ...
- bzoj1997 [HNOI2010]平面图判定Plana
bzoj1997 [HNOI2010]平面图判定Planar 链接 bzoj luogu 思路 好像有很多种方法过去.我只说2-sat 环上的边,要不在里面,要不在外边. 有的边是不能同时在里面的,可 ...
- 洛谷 P3209 [HNOI2010] 平面图判定
链接: P3209 题意: 给出 \(T\) 张无向图 \((T\leq100)\),并给出它对应的哈密顿回路,判断每张图是否是平面图. 分析: 平面图判定问题貌似是有线性做法的,这里给出链接,不是本 ...
- 洛谷P3209 [HNOI2010]平面图判定(2-SAT)
传送门 看到哈密顿回路就被吓傻了……结果没有好好考虑性质…… 首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass 然后考虑原图,先把哈密顿回路单独摘出来,就是 ...
- [HNOI2010]平面图判定
Description: 若能将无向图 \(G=(V, E)\) 画在平面上使得任意两条无重合顶点的边不相交,则称 \(G\) 是平面图.判定一个图是否为平面图的问题是图论中的一个重要问题.现在假设你 ...
- Luogu3209 HNOI2010 平面图判定 平面图、并查集
传送门 题意:$T$组数据,每组数据给出一个$N$个点,$M$条边,并存在一个$N$元环的图,试判断其是否为一个可平面图(如果存在一种画法,使得该图与给出的图同构且边除了在顶点处以外互相不相交,则称其 ...
- [HNOI2010] 平面图判定 planar
标签:二分图判定.题解: 首先可以把题目中给你的那个环给画出来,这样就可以发现对于任意一个图来说,如果两条边要相交,就不能让他们相交,那么这两条边就要一条在里面一条在外面,如果把环画成一条链,那么就是 ...
随机推荐
- selenium-python元素定位技巧(一)
在python-selenium元素定位中,有很多小技巧,在此记录总结 技巧一.尽量不要用可见的文本去定位 尽量不要用可见的文本去定位(特别是支持国际化的软件-比如禅道),因为一旦切换语言后,使用该方 ...
- Redis事务操作
Redis事务操作 Redis事务本质: 一组命令的集合 , 一个事务中的所有命令都会被序列化 , 在事务执行过程中 , 会按照顺序执行 一次性 : 事务之间的事情,会一次性执行,而不是立刻执行 ...
- 【NX二次开发】体消参,移除体参数UF_MODL_delete_body_parms()
例子: 源码: extern DllExport void ufusr(char *param, int *returnCode, int rlen) { UF_initialize(); tag_t ...
- Binding(二):控件关联和代码提升
上节我们讲到,使用Binding,我们可以关联后台代码中的属性,在某些情况下,我们可能需要将两个控件关联起来,借助Binding,我们也可以轻松的实现. 关联控件 设想这样一个场景,界面中有个Chec ...
- DOS命令行(2)——Windows磁盘维护与管理
预备知识 1 -- 磁盘 1.磁盘分区 主磁盘分区.扩展磁盘分区.逻辑分区 主磁盘分区是物理磁盘的一部分,它像物理上独立的磁盘那样工作.对于基本启动记录(MBR)的磁盘,在一个基本磁盘上最多可以创建四 ...
- 解决SpringMVC重复提交的问题
方法一:通过重定向采取请求转发的方式完成表单内容的添加会造成内容的重复插入.当向Servlet发送一条增加记录的请求后,servlet首先向数据库增加一条记录,然后又从数据库中查询出所有数据,接着转发 ...
- vue项目使用Echarts制作项目工期甘特图
目录 1,前言 2,布局和数据部分 3,制作甘特图 1,前言 项目迭代过程中,碰上一个需求,要求用甘特图的方式显示项目的工期进度,开完会我赶紧搜索一下甘特图是啥东东,大概了解之后,做出了如下样式 Ec ...
- excel VBA构造函数就是这么简单
Function test(a As Integer)'构造函数名字为test参数为a且为int型 If a >= 90 Then Debug.Print "优秀" ...
- zabbix_manage的使用
实验环境: zabbix server 172.16.1.121 访问端 172.16.1.122 55.1 说明 zabbix_manager是zabbix终端管理工具,可以在linux终端实现管理 ...
- 并发王者课-铂金10:能工巧匠-ThreadLocal如何为线程打造私有数据空间
欢迎来到<并发王者课>,本文是该系列文章中的第23篇,铂金中的第10篇. 说起ThreadLocal,相信你对它的名字一定不陌生.在并发编程中,它有着较高的出场率,并且也是面试中的高频面试 ...