平面图

平面图就是所有点的连边不相交的图。(当然是在你尽量想让它不相交的情况下)。这一点可以大概理解成拓扑图的性质,即每连一条边就会将某个区域进行分割——很明显,如果两个点分别处在两个不可达的区域,它们要连边显然是要穿过其他边的。

平面图定理

边数大于点数的三倍减六的图一定不是平面图。即设n为点数,m为边数,有

\[m<=n*3-6
\]

关于平面图的其他定理和上定理的证明我不会不过我有大佬博客就不乱搬了。

关于此题题解

首先,它给出了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-平面图判定的更多相关文章

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

    正解:2-sat(并茶几/强连通分量 解题报告: 传送门w 难受死了,连WA5次,正确率又-=INF了QAQ 然后先说下这题怎么做再来吐槽自己QAQ 首先这题其实和NOIp2010的关押罪犯挺像的,然 ...

  2. P3209 [HNOI2010]平面图判定

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

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

    P3209 [HNOI2010]平面图判定 题意 题目描述 若能将无向图\(G=(V,E)\)画在平面上使得任意两条无重合顶点的边不相交,则称\(G\)是平面图.判定一个图是否为平面图的问题是图论中的 ...

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

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

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

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

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

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

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

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

  8. [HNOI2010]平面图判定

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

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

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

  10. [HNOI2010] 平面图判定 planar

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

随机推荐

  1. 「题解」USACO15FEB Fencing the Herd G

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书: 题目 题目链接:洛谷 P3122.USACO 官网. 题意概述 给你平面上的一些点和直线,有两种操作: 新加入一个点 \((x,y)\): ...

  2. Hive窗口函数保姆级教程

    在SQL中有一类函数叫做聚合函数,例如sum().avg().max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.但是有时我们想要既显示聚集前的数据, ...

  3. JavaScript中基本数据类型和引用数据类型的区别(栈——堆)

    JavaScript中基本数据类型和引用数据类型的区别 1.基本数据类型和引用数据类型 ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型. 基本数据类型指的是简单的数据段,引用数据 ...

  4. 【模拟7.16】通讯(tarjan缩点加拓扑排序)

    这题确实水,纯板子,考试意外出错,只拿了暴力分QAQ tarjan缩点加上拓扑排序,注意这里求最短路径时不能用最小生成树 因为是单向边,不然就可能不是一个联通图了.... 1 #include< ...

  5. 再试Hibernate框架

    几个月前因为学习需要第一次接触了Hibernate(之前一直在用MyBatis),后来觉得有点难,也急着找工作,所以就没继续学下去了.但是找工作的时候发现Hibernate的需求更高,使用率更高,所以 ...

  6. Echarts中X轴坐标太密集,分段显示

    在axisLabel中设置刻度间隔interval,再加上强制显示最大值showMaxLabel和最小值showMinLabel axisLabel: {//X轴文字 interval: day == ...

  7. Golang获取CPU、内存、硬盘使用率

    Golang获取CPU.内存.硬盘使用率 工具包 go get github.com/shirou/gopsutil 实现 func GetCpuPercent() float64 { percent ...

  8. Java中对象初始化过程

    Java为对象初始化提供了多种选项. 当new一个对象的时候,对象初始化开始: 1.首先,JVM加载类(只加载一次,所以,即使多次new对象,下面的代码也只会在第一次new的时候执行一次),此时, 静 ...

  9. PUN丨实用API

    原文地址:PUN丨实用API 当前房间人数 int num = PhotonNetwork.CurrentRoom.PlayerCount; 当前脚本是否属于当前玩家 //需继承MonoBehavio ...

  10. C#获取字符串字符的位数(区分中文和英文长度)

    请看以下代码 1 private static int GetStrLength(string str) 2 { 3 if (string.IsNullOrEmpty(str)) return 0; ...