图论学习笔记五贪心算法

优化问题的算法通常会通过一系列的步骤,在每一个步骤通过一系列的选择。一个贪婪算法总是目前看起来最好的选择。也就是说,它做出局部最优选择,希望选择将导致全局最优的解决方案。贪心算法并不总是能得到最优解,但对于许多问题它们都能得到最优解。

活动选择问题

几个相互竞争的活动需要共同的资源,目标是在活动不发生冲突的前提下,选出最多可举办的活动数。假设我们有一个集合S=\{a_1,a_2,...a_n\}提议希望使用资源的活动,例如一次只能由一个活动使用的演讲厅。每个活动ai都有一个开始时间si和一个结束时间fi, 0\leq s_i\leq f_i<\infty。如果选择,活动ai发生在半开时间间隔[si,fi)的情况下,活动ai和aj是兼容的,间隔[si,fi)和[sj.fj]不重叠的。活动选择问题是选择相互兼容的活动的最大子集。

按开始时间最早的排序;X

按时间间隔最短的排序;X

按结束时间最早的排序;√

最小生成树问题(Minimum spanning trees,MST)

在电子电路的设计中,把几个零件的引脚连接在一起就通电了。互连一组n个引脚,我们可以使用一个n-1线的排列,每根连接2个引脚。在所有这些安排中,使用的那个最少的电线通常是最多的引脚。我们可以用一个连通的无向图G=(V,E)来建模这个布线问题,其中V是引脚的集合,E是引脚对之间可能的相互连接的集合,对于E中的每条边(u,v),我们都有一个权值w(u,v)来指定连接u和v的代价(所需的导线数量),需要找到无圈的子集T\subseteq E把所有的引脚连接起来,并使得权值w(T)=\sum_{(u,v)\in T}w(u,v)最小。因为T是非圈的,并且连接所有的顶点,所以它必须形成一棵树,我们称之为G的生成树,T就是最小生成树。

假设有一个连通的无向的图G=(V,E),及权值函数w:E\rightarrow R。我们希望找到G的最小生成树。我们在这里考虑的两个算法使用贪婪的方法解决问题。

这个贪心策略由下面的“一般型”算法延伸,该算法每次只增长最小生成树的一条边。该算法管理边集A,A不断加1条边,需要做n-1次循环。在每次迭代之前,A是最小生成树的子集。在每一步,我们确定可以添加到A的边{u,v},在不违背这个不变式的情况下,A\cup \{u,v\}还是最小生成树的一个子集。我们称这样的边为A的安全边,因为它可以在保持不变的情况下添加到A。

1
2
3
4
5
6
GENERIC-MST(G,w)
A ← ?
while A does not form a spanning tree
    do find an edge e that is safe for A
        A ← A ∪ e
return A

如何找到安全的边?

我们首先需要一些定义。无向图G=(V,E)的一个cut(S,V-S)是V的一个分划。如果它的一个端点在S中,另一个端点在V-S中,我们说一条在E中的边(u, v)穿过这个cut(S,V-S)。如果A中的边没有与该cut相交,则该cut respects A组边。如果边的权值是任何边穿过cut的最小值,则边就是穿过cut的轻边。注意,还可以有更多轻边,那么选择其中一条即可。简单来说,就是A+安全边就是最小生成树的子集,A中的点没有穿过cut,再在cut中找到轻边作为安全边,得到新的A,然后再找到新的cut,满足A没有穿过cut,循环此过程,直至找到n-1条边。

定理:设G=(V,E)是连通的具有权重w的无向图,令A是E的子集,包含在G的最小生成树中。设(S, V-S)为任意cut(respect A),设(u,v)为穿过(S, V-S)的轻边。那么(u,v)是A的安全边。

证明:设T是一个最小生成树,包含A,并假设T不包含轻边(u,v)。如果是这样,我们就完成了。我们将构造另一棵最小生成树T',通过使用cut-and包括U {U,v}粘贴技术,从而显示(u,v)是aA的安全边。

边(u,v)与在T中路径p从u到v的边形成一个循环,因为u和v是cut(S, v -S)的相对边,所以在路径p中至少有一条边也穿过cut。设(x,y)是任意一条这样的边。这条边(x,y)不在A中,因为cut respect A。因为(x,y)在T中从u到v的唯一路径上,所以删除(x,y)把T分成两个部分。添加(u, v),从新的生成树重新连接它们T'=T-(x,y)\cup (u,v)接下来证明T'是最小生成树。因为(u,v)是一个轻的边缘交叉(S, v -S)和(x,y)也穿过这条线,w(u,v)<=w(x,y)因此,w (T ') = w (T) - w (x, y) + w (u, v) < = w (T)。但是T是最小生成树,所以T'也必须是最小生成树。

对于当前生成树T,u,v之间没有直接的边相连,但可以通过路径p连通,按图中将G分割为cut两部分,使得u, v在cut不同的点集,那么必然存在这样 的x,y也被划分在cut两部分,边(u,v)(x,y)都穿过该cut,(u,v)是轻边,连接(u,v),断开(x,y),得到新的生成树T‘,而且(u,v)是轻边,那么T(w)≥T'(w)。

Kruskal , Prim它们使用特定的规则来确定安全边界。

克鲁斯卡尔算法(Kruskal)和Prim算法

集合A是一个森林。添加到A的安全边总是图中连接两个不同组件的最小权重边(即选择图G中未连接的权值最小的边)。在Prim的算法中,集合A形成一个单一的树。添加到A的安全边总是最小权值将树连接到不在树中的顶点的边(从当前解的生成树往外连接权值最小的边)。

Prim算法: 假设从a出发,先走ab,bc和ah的权值一样,任选一条,这里走bc,w(ci)

为了验证正确性,可以从任意点出发,再次选择一遍,结果是一样的,假设从d出发,下图是按d出发的cut选择。

Kruskal算法:按照权值从小到大连接,最小的是w(hg)=1,那么选择过程:hg,gf,ci,cf,ab,cd,cb,de。下图显示前五步选择。

最大独立集(Maximum independent set)

我们要找到最大的独立集合。如果我们用贪心算法解决问题,假设顶点的度越小越好。事实上,每当我们加上一个点到目前的解,我们也要把它的所有邻居都清除掉。因此,首先选择度较小的顶点可能会使我们获得一个最大的独立集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Greedy independent set
input Graph G=(V,E);
output independent set V' in G;
begin
    V':=ф
    U:=V
    while U is not empty do
    begin
        x: vertex of minimum degree in graph induced by U
        V':=V'U(x);
        eliminate x and all its neighbors from U
    end
    return V'
end

贪心算法找不到最大独立集的例子:

a是最小度的点,a放入解集,删除邻居b,c,d,剩下e,f,g任选一个点,那么最大独立集为两个点。但最大独立集是三个点{b,c,d}。

可以看出,存在一个顶点数不断增加的图序列,对于这个图序列,该算法所得到的解的度量值与最优值相差甚远。

可以使用图的密度函数判断贪心算法的表现。

定理:假设图G有n个点和m条边,记\delta =m/n为图G的密度。贪心算法求得的解m_{Gr}(G)\geq n/(2\delta +1)

证明:

证明:设xi为程序while循环第i次迭代时选定的顶点,di(删除邻居后子图的度)为xi的度。然后,该算法将xi及其所有di邻居从G中删除。第i步删除di+1个点,得到第一个式子\sum_{i=1}^{m_{Gr}(G)}(di+1)=n..........(1),又因为删除点的同时会删除边,那么与xi相连的di个点至少度是di,那么删除的边有(di+1)di,di个点之间可能存在互相连接的情况,那么删除的边至少有(di+1)di/2,删除的边数一定小于总边数,得到第二个式子\sum_{i=1}^{m_{Gr}(G)}(di+1)di/2\leq m=\delta n..........(2),(2)*2+(1)得到\sum_{i=1}^{m_{Gr}(G)}(di+1)^2\leq n(2\delta +1)。利用柯西斯瓦格不等式,对于所有的i,当di+1=n/m_{Gr}(G)时,不等式的左边取得极小值。n(2\delta +1)\geq \sum_{i=1}^{m_{Gr}(G)}(di+1)^2\geq n^2/m_{Gr}(G),定理得证。

下面的定理提供了最优解与贪婪算法求得的解之间的关系。

定理:有n个顶点和m的图G,设\delta =m/n。程序找到一个独立的集合m_{Gr}(G),令最优解m(G)/m_{Gr}(G)\leq (\delta +1)

证明:本证明与前一证明相似。在本例中,我们在在(2)中另外计算与某个最优解的顶点相关联的边的数目。即,确定一个最大的独立集合V*,令ki为在第i次循环中所删除di+1个顶点并在V*中的顶点数。明显地,\sum_{i=1}^{m_{Gr}(G)}k_i=|V*|=m*(G)............(3),由于贪心算法选择的顶点最小度,删除的顶点的度的和至少是di(di+1)。因为一条边的两个端点不可能都在V*中,它这样删除边的数目至少为(di(di+1)+ki(ki-1))/2,这里可以提高(2),得到\sum_{i=1}^{m_{Gr}(G)}\frac{di(di+1+ki(ki-1))}{2}\leq \delta n...........(4)),(2)+(3)+2*(4)得到\sum_{i=1}^{m_Gr(G)}((di+1)^2+ki^2)\leq n(2\delta +1)+m*(G)。应用CS不等式,当di+1=n/m_{Gr}(G)\ and\ ki=m*(G)/m_{Gr}(G),上述不等式左边最小,因此,n(2\delta +1)+m*(G)\geq \sum_{i=1}^{m_{Gr}(G)}((di+1)^2+ki^2)\geq \frac{n^2+m*(G)^2}{m_{Gr}(G)},即m_{Gr}(G)\geqm*(G)\frac{n/m*(G)+m*(G)/n}{2\delta +1+m*(G)/n},当m*(G)=n时,不等式最小。通过把这一项代入,定理就成立了。

背包问题(Greedy knapsack)

输入:集合X的n个元素,对于X中的每个xi,价值pi,重量wi,正整数b;

输出:子集Y\in X使得\sum_{xi\in Y}wi\leq b,max\ \sum_{xi\in Y}pi

按pi/wi的规则进行贪心选择。

1
2
3
4
5
6
7
8
9
10
11
begin
    sort X in non-increasing order with respect to the ratio pi/wi;
    Y:=empty set;
    for i=1 to n do
    if b>=wi then
    begin
        Y=YU{xi}
        b=b-wi
    end
    return Y
end

反例:

例:令pi=wi=1,i=1,2,..,n-1, pn=b-1, wn=b=kn,其中k是一个任意大的数。在这种情况下,最优解m*(x)=b-1;而贪心算法找到的解的值为n-1。因此m * (x) /mGr(x) > k。

发现贪心算法的劣势是由于算法没有将价值最高的元素包含在解中,而最优的元素正是价值最高的。这表明一个简单的修改贪心的程序有更好的性能。

定理:给定一个背包的实例x,令mH(x)=max(Pmax,mGr(x)),其中Pmax是x中一个项目的最大价值,mH(x)满足以下不等式:m*(x)/mH(x)< 2

证明:设j为根据贪心选择第一个装不进背包物品的下标,此时背包转装入的物品价值为\overline{p_j}=\sum_{i=1}^{j-1}\leq mGr(x),重量为\overline{w_j}=\sum_{i=1}^{j-1}w_i\leq b。我们首先证明任何最优解必须满足以下条件不等式:m*(x)<\overline{p_j}+p_j,(因为装入前j-1个物品后,容量还剩余b-\overline{w_j}< w_j,贪心选择在装入j-1个物品后,无法装入j,其密度为pj/wj,那么如果剩余容量按最优的去放,(b-\overline{w_j})\frac{p_j}{w_j}<w_j\frac{p_j}{w_j}=p_j)。如果p_j<\overline{p_j},那么m*(x)<2\overline{p_j}\leq 2mGr(x)\leq 2mH(x);如果p_j>\overline{p_j},那么Pmax>\overline{P_j},有m*(x)\leq \overline{p_j}+p_j\leq 2{p_j}\leq 2Pmax\leq 2mH(x)

The Stein-lovasz Theorem(ST)

定理:设A是一个N行M列(0,1)矩阵。假设每一行至少包含v个1,每一列至多包含a个1。然后存在一个NXK子矩阵C(没有全0行,每一行至少有一个1的矩阵)满足:K\leq N/a+(M/v)lna\leq (M/v)(1+lna)。可以想象为关联矩阵,每一列用超边连接,如何用最少的超边把所有的行覆盖掉,每条超边覆盖的点满足|B_i|\leq a,利用贪心策略,每一步的超边尽可能选最多的行。

选择B2,B3就可以把所有的行覆盖
选择B2那么前三行被覆盖,在剩余的行里找最大的超边

举例:

点集X={1,2,3,4,5,6},超边集合\Gamma={{1,3,4},{2,4,5},{1,5},{3,5},{5,6},{4},{6}},从超边集合选择最少的子集合,覆盖所有的行,那么选择{1,3,4},{2,4,5},{6}最少的超边子集合。

证明:

假设A_a=A_{N*M}A_a'表示由a个1且每列的1互不重合的列组成的矩阵,|A_a'|=K_a,那么删除覆盖的K_a\cdot a行得到新的矩阵A_{a-1}=A_{(N-aK_a)\times (M-K_a)},那么每一列至多有a-1个1,A_{a-1}'表示由a-1个1且每列的1互不重合的列组成的矩阵,|A_{a-1}'|=K_{a-1},那么删除覆盖的K_{a-1}\cdot (a-1)行得到新的矩阵A_{a-2},以此类推。A_{i-1},每行至少v个1,每列至多i-1个1,那么有N-aK_a-(a-1)K_{a-1}-...-iK_i行,令其记为k_i,有M-K_a-...-Ki列。k_a=N-aK_a,即K_a=\frac{N-k_a}{a},令N=k_{a+1},则K_a=\frac{k_{a+1}-k_a}{a},以此类推得到K_i=\frac{k_{i+1}-k_i}{i}\sum_{i=1}^{a}K_i=\sum_{i=1}^{a}\frac{k_{i+1}-k}{i}=\frac{k_{a+1}}{a}-\frac{k_a}{a}+\frac{k_a}{a-1}-\frac{k_{a-1}}{a-1}+...+\frac{k_2}{1}=\frac{N}{a}+\frac{k_a}{a(a-1)}+\frac{k_{a-1}}{(a-1)(a-2)}+...+\frac{k_2}{2\times 1}。使用双计数,分别对行和列进行计数,对于A_{i-1},每一行至少v个1,而每列至多i-1个1,可得对1进行行计数不会超过进行列计数,即k_i\times v\leq (M-K_a-...-K_i)\times (i-1)\leq M\times (i-1)\frac{k_i}{i-1}\leq \frac{M}{v},那么\sum_{i=1}^{a}K_i\leq \frac{N}{a}+\frac{1}{a}\frac{M}{v}+\frac{1}{a-1}\frac{M}{v}+...+\frac{1}{2}\frac{M}{v}=\frac{N}{a}+\frac{M}{v}(\frac{1}{a}+\frac{1}{a-1}+...+\frac{1}{2})\leq\frac{N}{a}+\frac{M}{v}lna\leq\frac{M}{v}+\frac{M}{v}lna=\frac{M}{v}(1+lna)

应用:

1. 完美哈希族

(n,m,w)-完美哈希族是一个函数F集合,使得|Y|=n, |X|=m, f:Y\rightarrow X对于F中的每一个f,对于任何C\subseteq \{1,2,...,n\}使得|C|=w,C是Y的w元子集合,并且至少存在一个F中的f使得f|C是一一对应的。如果|F|=N那么完美哈希族可以记作PHF(N;n,m,w)。

|F|=N,如上图,假设w=3,那么任选Y中的三列,有\binom{n}{3}种选择,要求其中存在一行使得三个函数值各不同,例如取1,2,3列,f11,f12,f13互不相同就满足要求一一映射。

f:Y\rightarrow X,n个Y对应到m个X,每一个Y有m种选择,那么有m^n个函数。从中挑出最少的函数(即上图的N越小越好)使得对于任何的C可以满足一一对应要求。

套用ST定理,找到对应的N,M,v,a,套用公式,就可以得到函数数目的一个上界。

需要完成的事情N:\binom{n}{w},从M:m^n个函数中挑选出最少的函数满足要求,那么得到的矩阵就是NxM的(0,1)矩阵A,Aij=1的含义就是当|w|=i,fj是可以满足一一映射要求的。v:\binom{m}{w}w!\cdot m^{n-w},表示从m个值中选取w的值排列放入选择的w个,剩余未赋值的n-w个,就任意赋值。a:\binom{n}{w},每一个函数至多覆盖a个。套用ST定理得N\leq \frac{m}{w!\binom{m}{w}}(1+log\binom{n}{w})

使用概率方法,从m^n个函数中随机选择N个函数出来,构造一张随机的函数表,考虑坏概率,在函数表中没有一个函数可以使w存在一一映射关系,对于一个函数坏概率为存在一一对应关系的对立事件,取出N个函数,得(1-\frac{\binom{m}{w}w!m^(n-w)}{m^n})^N\binom{n}{w},使其小于1,那么一定存在完美哈希族。(两边取对数求解)

2.分割系统(Splitting Systems)

在某个域中,\alpha ^n=\beta\alpha ,\beta已知且为离散的,那么如何求解n?分割系统的提出就是为了解决离散对数问题。

假设n,t为偶数,0)(X是点集合,B是超边集合):

a) |X|=n, B是X的n/2子集的集合,称为区组

b)对于每一个Y\subseteq X使得IY|=t,在B中存在区组B,使得|B\cap Y|=t/2

最少N的B使得上面的条件满足。

使用ST定理N:\binom{n}{t},对所有的t元子集合进行分割,M:\binom{n}{n/2},完成的方法总数,接下来确定v,那么对于某一行有多少n/2元子集合可以分割ti,t个位置中一半放1,剩余一半放0,问题是一个n元集合,此时还剩n-t个位置没有放数,且还缺少(n-t)/2个1,那么得到子集合个数\binom{t}{t/2}\cdot \binom{n-t}{\frac{n-t}{2}};确定a,对于固定的n/2元子集合可以分割多少t,\binom{n/2}{t/2}\binom{n/2}{t/2},套用ST定理,N\leq \frac{\binom{n}{n/2}}{\binom{t}{t/2}\binom{n-t}{(n-t)/2}}(1+2ln\binom{n/2}{t/2})

使用概率方法:

定义Ai,第i个t元子集合未被分割。对于一个t元集合没有分割的概率是分割时间的对立事件,为1-\frac{\binom{t}{t/2}\binom{n-t}{(n-t)/2}}{\binom{n}{n/2}},共有N个n/2元子集合未被分割,为(1-\frac{\binom{t}{t/2}\binom{n-t}{(n-t)/2}}{\binom{n}{n/2}})^N=P(Ai),那么至少有一个t元集合未被分割的概率为P(\cup Ai)\leq \sum P(Ai)=\binom{n}{t}P(Ai)<1,令其小于1,那么没有未被分割的情况概率大于0。