平面图的简要介绍及若干定理


做到“[HNOI2010]平面图判定”这道题的时候用到了平面图的性质,于是来学学。
Reference1
Reference2


平面图的定义

若简单图 \(G=(V,E)\) 能画在平面上使得任意两条无重合顶点的边不相交,则称 \(G\)平面图(Planar Graph)。将 \(G\) 中由边构成的且不能再划分成更小子区域的区域称为平面图 \(G\)(Face),包围这个区域的边称为面的边界(Bound),其中由平面图外部边界组成的面称为外部面无限面(Exterior Face)。一个面 \(R\) 的边界的边数称为面的,记为 \(\deg(R)\)。除了割边外,任何一条边都属于两个面的边界。

下面举几个例子。
Fig1. 一副非平面图。可以发现无论如何调整点与边的位置都无法让边不相交。

Fig2. 从 PPT 上盗的,关于平面图及其各个面。

若干定理

定理 1 一个有限平面图,其面的度之和等于其边数的两倍,即

\[\sum_{R\subset E}\deg(R)=2e \]

根据前面的描述,定理 1 显然成立。
定理 2(欧拉公式) 任何一个凸多面体(联通平面图)满足关系式

\[v-e+r=2 \]

其中 \(r\) 为图的面数。
证明:对 \(e\) 施以归纳法。对于 \(e<2\) 的情况显然成立。现在假设小于 \(e\) 的情况成立,考虑 \(e\) 条边的图 \(G\) 的情况。

  1. 若第 \(e\) 条边一端为原来的点,一端为一个新的点,这时整幅图增加了一个顶点与一条边,面数不变,此时结论显然仍成立。
  2. 若第 \(e\) 条边两端都为原来的点,则整幅图增加了一个面与一条边,顶点数不变,此时也满足结论。

综上,定理得证。
定理 2 的推论 设平面图 \(G=(V,E)\)\(k\) 个连通块构成,则满足关系式

\[v-e+r=k+1 \]

根据之前所证,这个推论是显然的。
定理 3 对于任意一个 \(v\ge 2\) 的联通平面图,满足

\[e\le 3v-6 \]

证明:设 \(G\)\(r\) 个面,由于每个面至少由三条边组成,所以有

\[\sum_{R\subset E}\deg(R)\ge 3r \]

又由定理 1 知 \(2e\ge 3r\),代入欧拉公式消去 \(r\)\(e\le 3v-6\),证毕。
这个结论相当重要,请务必牢记。
定理 3 的推论 任何联通平面图中,至少存在一个其度不超过 \(5\) 的节点。
证明没看懂不过这个推论是很弱的,因为有很多非平面图也满足这个性质。

超简单的小练习:证明 \(K_{3,3}\)\(K_5\) 是非平面图(套定理 3 就完事了)。

过家家级别的定理说完了,接下来请抓紧扶好,我们要跳级了

Kuratowski 定理

Kuratowski 定理定性地说明了平面图的本质。
在说这个定理之前,先引出一个定义:对于图 \(G=(V,E)\) 的一条边 \((u,v)\),先删去这条边,然后增加一个节点 \(w\),并连接 \((u,w),(v,w)\),这样操作后所得的图称为原图的细分图

Fig3. 从巨佬的 blog 上盗的,细分图的例子。

Kuratowski 定理 一个图是平面图当且仅当它不包含与 \(K_{3,3}\)\(K_5\) 的细分图同构的子图。
也就是说,如果 \(K_{3,3}\)\(K_5\) 可以通过不断细分变成这副图,则这幅图是非平面图。(可以通过 Fig1 加深理解)
证明?没找到……并且我还看见了这个……
口区
行吧,所以虚晃一枪 qwq


[HNOI2010]平面图判定 题解

好吧这其实才是我真正要说的……
这题还是很神的,一是有个没见过的东西,二是对图的处理属实毒瘤。
首先注意到这题 \(m\le 10000\),但 \(n\le 200\),于是可以用上面的定理 2 把 \(m\) 的范围缩小。
接下来如何判定这是个平面图呢?似乎很棘手,但注意到这道题的图有个特殊性质就是存在哈密顿圈。我们可以把这个哈密顿圈看成一个圆,除去在哈密顿圈上的边后剩下的都是圆上的弦,那么如何判断两弦相交呢?考虑对于两条弦 \((x,y),(u,v)\),其中 \(x,y,u,v\) 都是哈密顿圈上的顺序编号,如果有 \(x<u<y<v\),那么这两条弦就相交了。
于是对于每条弦,我们都要维护它的互斥关系,因为一条弦可以选择画在圆内或圆外来避免冲突,对于无法避免冲突的情况,就判定为非平面图。
如何维护互斥关系?这随便,二分图、并查集、2-SAT 心情好写哪个。(我用了并查集,好写👌

#include <bits/stdc++.h>
using namespace std;

const int N=1e5+5;
int n,m,fa[N],X[N],Y[N],id[N];

int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} 
bool check()
{
    for(int i=1;i<=m;++i) if(find(i)==find(i+m)) return 0;
    return 1;
}

int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i) scanf("%d%d",&X[i],&Y[i]);
        for(int i=1,x;i<=n;++i) scanf("%d",&x),id[x]=i;
        if(m>3*n-6) {puts("NO"); continue;}
        for(int i=1;i<=m<<1;++i) fa[i]=i;
        for(int i=1,a,b;i<=m;++i)
        {
            a=id[X[i]],b=id[Y[i]];
            X[i]=min(a,b),Y[i]=max(a,b);
        }
        for(int i=1;i<m;++i)
            for(int j=i+1;j<=m;++j)
            {
                if(Y[i]==X[i]+1||(Y[i]==n&&X[i]==0)) continue;
                if(Y[j]==X[j]+1||(Y[j]==n&&X[j]==0)) continue;
                if(X[i]==X[j]||Y[i]==Y[j]||X[i]==Y[j]||X[j]==Y[i]) continue;
                if((X[i]<X[j]&&Y[i]<Y[j]&&X[j]<Y[i])||
                   (X[j]<X[i]&&Y[j]<Y[i]&&X[i]<Y[j]))
                        fa[find(i)]=find(j+m),fa[find(j)]=find(i+m);
            }
        puts(check()?"YES":"NO");
    }
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM