我是一个数学工作者,专业方向是图论。研究图论已经十年有余。一个月前,一个偶然的机会让我萌生了一个念头,那就是我想尝试用C++写出我所学过的图论方面的算法。作为一个数学工作者,过去一直是纸上谈兵,我之前并没有真正写过多少程序。确实,只知道写证明的纯理论的数学工作者往往自视甚高地看不起工程中实际写程序的程序员(即使程序员圈子里也有不少厉害的数学工作者),另一个方向的鄙视链好像也一定程度上存在着。于是,我不想只作一个“思想上的巨人行动上的矮子”,便有了这个系列的博客。
首先声明,我不是专业的程序员,只是大学里教数学的一个教书匠。程序写得不好还请诸位指教。另一方面,工作上压力也蛮大,有不少教学工作和论文方面的工作。所以我的博客可能无法定期更新。
然后说说我们的主要目标。目前我的目标是写一下有关“图的顶点染色”方面的算法,如果我足够“有毅力”可以坚持下去的话(其实,之前也想做这件事情,后来都慢慢放弃了),将来看情况再写写其他方面,甚至于纯粹的离散数学方面的内容。下面开始正题。
(一)图论和顶点染色的相关简介。
图论的研究对象是“图”,我们在数学上一般用G,H,F这几个字母表示。设G是一个图,一般认为G有两部分组成,分别是顶点集V(G)和边集E(G),它们有时也简写作V和E,因而有时也将图G更准确地表示为G(V,E)。画在纸上看,一般是用小圆点表示图的顶点,而用连接两个小圆点的线表示边。实际上,这恰恰暗示着图G还有隐含的第三个部分,那就是顶点和边的关联关系,一般说,边e与顶点u和v相关联,直观上看,就是图上有一条线e将顶点u和v相连。由于这些“线”实际上只是体现逻辑上的关联关系,所以这些具体的画法一般没有什么要求,当然笔者专业的拓扑图论以及和图论有些沾边的“组合几何学”(几何图论)有些例外,一般情况下是不做要求的。
设e是一个边,它关联的两个顶点是u和v,则称u和v是它的两个端点,并且称u和v是相邻的。如果u=v,那么我们称这个边e是一个loop(国内中文书里翻译这个loop有好几种名字,为了不造成混乱,涉及学术名词时,我尽量保持英文表述,除非中文已经有了确切的约定俗成)。如果关联着u和v的边不只一条,那么我们就称这一组边是一组平行边(也叫重边)。如果一个图没有平行边也没有loop,那么我们就称这种图是一个简单图(simple graph)。
下面说一下顶点染色。考虑图G(V,E)。设c是一个从V到集合{1, 2, ... , k}的映射(如果“映射”这个词你听起来不习惯,也可以把它换成“函数”,完全没毛病),那么我们就说c是图G上的一个k-顶点染色,简称k-染色(k-colouring),c的像集(或者说值域){1, 2, ... , k}中的每个数字都叫做这个染色所用的颜色。如果进一步地,染色c能保证:任何边不会连接颜色相同的顶点,那就说这个染色c是好的(proper)。
设c是图G的所有好的染色中颜色个数最少的一个,那么就说c是G的最优的顶点染色,并且称c所用的颜色个数是G的色数(chromatic number),记作χ(G)。求图G的色数的问题就是“图的顶点染色问题”。
(二)游戏怎么玩?
1. 从图的顶点染色的定义可以看出,平行边的存在在染色问题中是没有意义的,而loop的存在在染色问题中是致命的。所以,我们在染色问题中只考虑简单图。
2. 我们的程序需要用各种算例来检验,我将把这些算例用文本文件的形式存储。每个算例都是一个随机图,它的每条边的存在性由一个指定的概率给出,换言之,这个图的边集是等概率的。所以我们首先需要一个生成随机图的程序,这个程序将在下一篇中给出,要求是输入两个参数,一是图的顶点数,二是每条边出现的概率。这两个参数能控制图的稠密程度,一般来说,图越稠密顶点染色的程序的实际耗时很可能越大,所以它们将是十分重要的参数。
3. 以后的算法中会出现其他一些概念,由于涉及图论概念可能很多,所以我将不会一次性写完,而是每次只写这一篇所需要的概念。并在文章结尾处留下本篇所涉及者。
(三)本篇所列概念(依照出现次序)
图;顶点集V(G);边集E(G);关联关系;
端点;相邻的顶点;loop;平行边,重边;简单图;
k-顶点染色,k-染色;颜色;好的染色;
最优的顶点染色;色数χ(G);图的顶点染色问题。