图论算法摘要
一个图(graph) G = ( V , E ) G=(V,E) G=(V,E) 由顶点(vertex)集 V V V 和边(edge)集 E E E 组成。
每一条边就是一个点对 ( a , b ) , a , b ∈ V (a,b),a,b∈V (a,b),a,b∈V。有时候也把边叫做弧(arc)。
如果点对 ( a , b ) , a , b ∈ V (a,b),a,b∈V (a,b),a,b∈V是有序的,那么图就是有向的(directed)。即 ( a , b ) (a,b) (a,b)和 ( b , a ) (b,a) (b,a)指不同的边。即这条边必须从点a指向点b,而不能反过来。
有向的图称为有向图(digraph)。
顶点 m m m 和 n n n邻接当且仅当 ( m , n ) ∈ E , m , n ∈ V (m,n)∈E,m,n∈V (m,n)∈E,m,n∈V
如果点对 ( a , b ) , a , b ∈ V (a,b),a,b∈V (a,b),a,b∈V是无序的,那么图就是无向的(directed)。即 ( a , b ) (a,b) (a,b)和 ( b , a ) (b,a) (b,a)指同一条边。
无向的图称为无向图(digraph)。
有时候边还能有第三种成分,称作权(weight)或值(cost)。
P问题:能够在多项式时间内可用算法求解的问题
NP问题:非确定型多项式时间(nondeterministic polynomial-time)问题。
不可判定问题(undecidable problem):"不可能“解出的问题
P问题的例子:
假设图 G = ( V , E ) G=(V,E) G=(V,E) 由顶点(vertex)集 V V V 和边(edge)集 E E E 组成。顶点集 V V V存在子集 V s u b V_{sub} Vsub,边集 E E E存在子集 E s u b E_{sub} Esub。
欧拉回路问题:找出一条路径恰好经过 E s u b E_{sub} Esub 每条边一次,计算复杂度为 O ( n ) O(n) O(n)
NP问题的例子:
哈密顿圈问题:找出一个简单圈,该圈包含 V s u b V_{sub} Vsub 的每一个顶点;通过图G的每个结点一次,且仅一次的通路(回路),就是哈密顿通路(回路),也称哈密顿圈。存在哈密顿圈的图就是哈密顿图。尚且不知道有线性算法。更进一步地,哈密顿圈问题是NPC问题。
不可判定问题的例子:
停机问题:让C编译器能够检查语法错误和所有无限循环
难度:P问题
不是所有可判定问题都是NP。例如无哈密顿圈问题不确定是否属于NP。
与NP相关的总共有四类问题:P问题、NP问题、NPC问题和NP hard问题,是计算复杂度理论中研究的主要内容之一。
P类问题:所有可以在多项式时间内求解的判定问题构成P类问题。判定问题:判断是否有一种能够解决某一类问题的算法的研究课题。
NP类问题:所有的非确定型多项式时间可解的判定问题构成NP类问题。由于解本身显然提供了验证方法,因此NP类问题包括所有具有多项式时间解的问题。但是,既然验证一个答案比提供一个答案容易得多,而且NP只保证了验证算法具有多项式时间,因此在NP中就会存在不具有多项式时间解法的问题。然而,这样的问题至今未被发现。
针对NP问题有一个千年难题,即NP=P?,
也即是否所有能在多项式时间内验证得出正确解的问题,都是具有多项式时间求解算法的问题?
至今尚未有定论。问题来源:
在一个周六的晚上,你参加了一个盛大的晚会。由于感到局促不安,你想知道这一大厅中是否有你已经认识的人。你的主人向你提议说,你一定认识那位正在甜点盘附近角落的女士罗丝。不费一秒钟,你就能向那里扫视,并且发现你的主人是正确的。然而,如果没有这样的暗示,你就必须环顾整个大厅,一个个地审视每一个人,看是否有你认识的人。
生成问题的一个解通常比验证一个给定的解时间花费要多得多。这是这种一般现象的一个例子。与此类似的是,如果某人告诉你,数13,717,421可以写成两个较小的数的乘积,你可能不知道是否应该相信他,但是如果他告诉你他可以因式分解为3607乘上3803,那么你就可以用一个袖珍计算器容易验证这是对的。
人们发现,所有的完全多项式非确定性问题,都可以转换为一类叫做满足性问题的逻辑运算问题。既然这类问题的所有可能答案,都可以在多项式时间内计算,人们于是就猜想,是否这类问题,存在一个确定性算法,可以在多项式时间内,直接算出或是搜寻出正确的答案呢?这就是著名的NP=P?的猜想。
不管我们编写程序是否灵巧,判定一个答案是可以很快利用内部知识来验证,而没有这样的提示而需要花费大量时间来求解,被看作逻辑和计算机科学中最突出的问题之一。它是斯蒂文·考克于1971年陈述的。
这里规约的意思是将一个特殊问题一般化,即将原问题推广为一个最一般的、最有概括性、也更难的、计算复杂度更高的问题,这个问题具有最高的计算复杂度,如果这个最一般的问题也能有多项式时间求解算法,那么那些特殊的原问题也能有多项式时间求解算法。
解决了这个NP hard问题,所有NP问题都能够被解决了。
解决了这个NPC问题。所有NP问题都能够被解决了。
你会经常看到网上出现“这怎么做,这不是NP问题吗”、“这个只有搜了,这已经被证明是NP问题了”之类的话。你要知道,大多数人此时所说的NP问题其实都是指的NPC问题。他们没有搞清楚NP问题和NPC问题的概念。NP问题并不是那种“只有搜才行”的问题,NPC问题才是,NPC是最难的NP问题。
"NP问题一直都是信息学的巅峰。巅峰,意即很引人注目但难以解决。在信息学研究中,这是一个耗费了很多时间和精力也没有解决的终极问题,好比物理学中的大统一和数学中的哥德巴赫猜想等。
目前为止这个问题还“啃不动”。但是,一个总的趋势、一个大方向是有的。人们普遍认为,P=NP不成立,也就是说,多数人相信,存在至少一个不可能有多项式级复杂度的算法的NP问题。人们如此坚信P≠NP是有原因的,就是在研究NP问题的过程中找出了一类非常特殊的NP问题叫做NP-完全问题,也即所谓的 NPC问题。C是英文单词“完全”的第一个字母。正是NPC问题的存在,使人们相信P≠NP。
NPC问题目前没有多项式的有效算法,只能用指数级甚至阶乘级复杂度的搜索。
NP-Hard放宽了限定条件,它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决。"[4]
最后引用一下资料[3] [总结]算法中的P问题、NP问题、NP完全问题和NP难问题关于这几个问题的解释,因为太形象了,基本不需要修改,所以就直接搬运了:
"著名的NP类问题:旅行家推销问题(TSP)。即有一个推销员,要到n个城市推销商品,他要找出一个包含所有n个城市的环路,这个环路路径小于a。我们知道这个问题如果单纯的用枚举法来列举的话会有 ( n − 1 ) ! (n-1)! (n−1)! 种,已经不是多项式时间的算法了,(注:阶乘算法比多项式的复杂)。那怎么办呢?我们可以用猜的,假设我人品好,猜几次就猜中了一条小于长度a的路径,我画画画画,好的,我得到了一条路径小于a的环路,问题解决了,皆大欢喜。可是,我不可能每次都猜的那么准,也许我要猜完所有种呢?所以我们说,这是一个NP类问题。也就是,我们能在多项式的时间内验证并得出问题的正确解,可是我们却不知道该问题是否存在一个多项式时间的算法,每次都能解决他(注意,这里是不知道,不是不存在)。
所以这就引出了这类讨论的一个千年问题:是否 NP类问题=P类问题?
即,是否所有能在多项式时间内验证得出正确解的问题,都是具有多项式时间算法的问题呢?
太让人震惊了,要是解决了这个问题,那岂不是所有的NP问题都可以通过计算机来解决?
圣战的结果是,有的存在,有的不存在。=_=
在这场圣战中,人们还发现了很多的东东,也就是我们接下来要介绍的NPC问题和NPH问题。
为了证明这个千古难题,科学家想出了很多办法。其中之一就是问题的约化。所谓问题约化就是,可以用问题B的算法来解决A ,我们就说问题A可以约化成问题B。举个例子,一元一次方程的求解,跟二元一次方程的求解,我们知道,只要能求解二元一次方程,那就可以用二元一次方程的解法来求解一元一次方程,只需要将一元一次方程加上y,并附加一个方程y=0就可以将一元一次方程变形为一个二元一次方程,然后用二元一次方程的解法来求解这个方程。注意,这里二元一次方程的解法会比一元一次的复杂。所以我们说,只需要找到解二元一次方程的规则性解法,那就能用这个规则性解法来求解一元一次方程。从这里也可以看出,约化是具有传递性的,如A约化到B,B约化到C,A就可以约化到C,同时不断约化下去,我们会发现一个很惊人的特性,就是他一定会存在一个最大的问题,而我们只需要解决了这个问题,那其下的所有问题也就解决啦!这就是我们所说的NPC问题的概念!!!
引到NP问题里就是,对于同一类的所有的NP类问题,若他们都可以在多项式时间内约化成最难的一个NP类问题,(我们直观的认为,被约化成的问题应具有比前一个问题更复杂的时间复杂度)当我们针对这个时间复杂度最高的超级NP问题要是能找到他的多项式时间算法的话,那就等于变向的证明了其下的所有问题都是存在多项式算法的,即NP=P!!!!给出NPC问题定义,
NPC问题:如果所有np问题都能在多项式时间内转化为他,则称该np问题为npc问题(NPC:NP
complete又叫NP完全问题)
NPC问题是NP问题的子集。
当然,很多时候NPC问题是找不到一个多项式时间算法的,更多时候他是一个指数级的算法。
最后介绍下NPH问题。
NPH问题:我们又叫NP难问题,他不是一个NP问题,然后所有的NPC问题都可以在多项式时间内转化为他的话,我们就叫他NPH(hard)问题。"
时间复杂度并不是表示一个程序解决问题需要花多少时间,而是当问题规模扩大后,程序需要的时间长度增长得有多快。[4]
“也就是说,对于高速处理数据的计算机来说,处理某一个特定数据的效率不能衡量一个程序的好坏,而应该看当这个数据的规模变大到数百倍后,程序运行时间是否还是一样,或者也跟着慢了数百倍,或者变慢了数万倍。不管数据有多大,程序处理花的时间始终是那么多的,我们就说这个程序很好,具有 O ( 1 ) O(1) O(1)的时间复杂度,也称常数级复杂度;数据规模变得有多大,花的时间也跟着变得有多长,这个程序的时间复杂度就是 O ( n ) O(n) O(n),比如找n个数中的最大值;而像冒泡排序、插入排序等,数据扩大2倍,时间变慢4倍的,属于 O ( n 2 ) O(n^2) O(n2)的复杂度。
还有一些穷举类的算法,所需时间长度成几何阶数上涨,这就是 O ( a n ) O(a^n) O(an)的指数级复杂度,甚至 O ( n ! ) O(n!) O(n!)的阶乘级复杂度。
不会存在 ( 2 ∗ n 2 ) (2*n^2) (2∗n2)的复杂度,因为前面的那个“2”是系数,根本不会影响到整个程序的时间增长。同样地, O ( n 3 + n 2 ) O (n^3+n^2) O(n3+n2)
的复杂度也就是 O ( n 3 ) O(n^3) O(n3)的复杂度。
因此,我们会说,一个 O ( 0.01 ∗ n 3 ) O(0.01*n^3) O(0.01∗n3)的程序的效率比 O ( 100 ∗ n 2 ) O(100*n^2) O(100∗n2)的效率低,尽管在n很小的时候,前者优于后者,但后者时间随数据规模增长得慢,最终 O ( n 3 ) O(n^3) O(n3)的复杂度将远远超过 O ( n 2 ) O(n^2) O(n2)。
我们也说, O ( n 100 ) O(n^{100}) O(n100)的复杂度小于 O ( 1.0 1 n ) O(1.01^n) O(1.01n)的复杂度。(多项式时间小于指数级时间)
容易看出,前面的几类复杂度被分为两种级别,其中后者的复杂度无论如何都远远大于前者:一种是 O ( 1 ) , O ( l o g ( n ) ) , O ( n a ) O(1),O(log(n)),O(n^a) O(1),O(log(n)),O(na)
等,我们把它叫做多项式级的复杂度,因为它的规模n出现在底数的位置;另一种是 O ( a n ) O(a^n) O(an)和 O ( n ! ) O(n!) O(n!)型复杂度,它是非多项式级的,其复杂度计算机往往不能承受。当我们在解决一个问题时,我们选择的算法通常都需要是多项式级的复杂度,非多项式级的复杂度需要的时间太多,往往会超时,除非是数据规模非常小。” [4]
[1] NP问题、NP难问题(NPH)和NP完全问题(NPC)理解
[2] 百度百科——NP完全问题
[3] [总结]算法中的P问题、NP问题、NP完全问题和NP难问题
[4] 什么是P问题、NP问题和NPC问题