基本的图算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.
要求对于邻接矩阵和邻接链表给出从G 到T
G 的算法,并计算其复杂度。
对于邻接矩阵问题十分简单,直接求矩阵的转置即可,意味着把行换成列,把列换成行,对每行操作为O(|V|),需要对|V|行操作,时间复杂度为O (|V|^2)。
对于邻接链表,很明显要遍历链表的所有结点来看:如果对于u 结点其指向的结点中有v,则在新的链表中,创建一条从v 的链表指向u 的路径,因此需要遍历所有的链表元素,因此时间复杂度为O (|V|+|E|)。
3. 给出一个多图(多图为包含重复边和自循环边的图)去除冗余边的复杂度为O(V+E)的算法。
遍历邻接链表的所有结点,对于结点u ,如果其链表中还有u ,则去除所有的u ;如果还有重复的v ,则去除除了第一个v 以外的v 结点(这里的标记方法有很多种,可以用个数组)。这样的复杂度应该在O(V+E)。
4. 求解平方图的问题
算法如下:遍历G 的邻接矩阵,对于结点u ,如果存在u 到v 的路径,则在G^2的邻接矩阵u 中加入v,然后再遍历v 结点的链表,如果存在v 到w ,则将w 也加入到G^2的邻接矩阵u 中。
时间复杂度:这样,再遍历u 的时候,如果遍历到了u →v 这条边,那就在看v 的链表,而v 的链表里最多有|V|个结点,因此总的复杂度为O (|V|+|V|·|E|)。
6. 邻接矩阵求通用汇点(入度为|V|-1但是出度为0)的算法
算法如下:从(1,1)开始扫描邻接矩阵,如果(i,j )是0,则下一个扫描(i,j+1);如果(i ,j )是1,则下一个扫描(i+1,j ),当i 或者j 任一方到达|V|时停止。
这样,在最坏的情况下,扫描一行加一列或者一列加一行的结点,一共有2*|V|-1时间复杂度,因此为O(V)。
7. 关联矩阵,说明BB^T 每个元素是什么意思。
其中bij = -1 (如果边j 从结点i 发出)
1(如果边j 进入i 结点) 0(其他)
此处需要分类讨论:要明白B^T 中i 行相当于B 中第i 列。
①BB^T 对角线上的元素,T
B B (i ,i ) =
∑=|
E |1
j 2
bij
,这样如果存在一条由i 发出或者进
入i 的边,都会在T B B (i ,i )中加一(因为就算是-1平方之后也是1),因此T
B B (i ,i )就是代表由多少条边从i 发出或者进入。
②BB^T 非对角线元素,T
B B (i ,j ) =
∑=|
|1
k E jk ik
b b
,由公式或者读者自己画矩阵图可以
得出,如果k 边从i 发出从j 进入,或者反过来,bik*bjk 就等于-1,否则就为0。原因是i,j
不可能位于k 边的同一侧,所有必然一正一负。如果k 不通过i 或者不通过j ,则其中一个为0,而结果为0。因此T B B (i,j )可以表示存在多少i,j 之间的边,但是加了一个负号。
8. Adj[u]每个项不是链表而是散列表,包含(u ,v )这条边在图中存在的结点v 。判断一条边是否在图中存在的期望时间是多少?
期望的时间是O(1),但是最差情况下要扫描所有结点,因此是O(V)。运用二叉树搜索可以将最坏的时间降低为O(lgV),但是期望时间变坏,因为没有散列表的概率了。
22.2广度优先搜索
广度优先搜索的复杂度为O(V+E),其中O(V)为初始化的复杂度,O(E)为扫描邻接链表复杂度。
1——2:略
3. 使用单个位来表示颜色,单个位只能表示位0/1,因此颜色只有白和灰,黑色无法表示,因此删除第十八行对每个结点扫描结束后赋值为黑色的一行代码。
证明:直接一想就可以,代码第十三行,v.color==WHITE才会进行处理,灰色同样不处理,而算法最后之所以设置为黑色,是为了在研究算法的过程中给出一个更加形象的说明而已。
4.如果换成邻接矩阵的话,BFS的时间复杂度将变为多少
如果换成邻接矩阵,在扫描队列中结点i的时候,必须将mat(i,-)这一行所有的结点都扫描1遍,复杂度为O(V),而扫描队列中每个结点,因此复杂度为O(V^2)。
5.证明:在广度优先算法里,赋给结点u的u.d值与结点在邻接链表里出现的次序无关。使用下图为例子,证明:BFS所计算出来广度优先树可以因邻接链表中的次序不同而不同。
证明:①即使在邻接链表出现的次序不同,根据广度优先搜索的算法,这些结点的u.d 值都是u.pai.d+1(pai一概表示为先驱结点),因此与次序无关。
②广度优先树也是前驱子图。读者可行根据上图进行证明,过于简单不再细细解释,提示:t,x在链表中的不同顺序可能会导致生成两种不同的树。
6.请你举出一个图和一个树边的例子,图中源点到某一点的最短路径也是树边中的一条简单路径,但是无论在邻接链表中结点的顺序怎么排列,都无法通过BFS找到这树边。
就这样一个图,无论2,5在结点1中的顺序如果,都无法找到以下树边:
因为在BFS中,3,4总会连在同一个结点上。
7.根据时间复杂度为O(n+r)很明显可以看出这是一个BFS的应用,对BFS稍加修改就可以对链表进行处理分出娃娃脸型和高跟鞋型。
8.给出一个有效算法来求树的直径,树的直径就是树的所有最短路径中的最大值。
宽度优先搜索算法恰好可以求最短路径,从树的根节点s开始运行BFS(G,s),找出最后一个结点u,然后再运行以此BFS算法BFS(G,u),这次找到宽度优先搜索的最后一个结点v的v.d值就是树的直径。时间复杂度等同于BFS为O(V+E),在官方给出的答案中这里的时间复杂度为O(V),因为在树中边的数量和结点的数量是相关的(|E| = |V|-1),因此此处的时间复杂度进一步简化可以简化到O(V)。
9.G为一个连通无向图,给出一个算法在O(V+E)时间内计算图G中这样一个路径:该路径正反通过E中每条边恰好正反一次。
图G为一个无向图,找一个路径正好正反通过E中每条边,这个很像一个欧拉回路的问题。也类似与用BFS生成一个树。
Make_Path(u){
从u开始,如果G中存在u——v的路径并且v不在树中,则创建一个到v再返回u的环,这时候相当于设置v.pai = u;
然后遍历每个u——v的v,如果v不等于u.pai,则创建一条到v的路径并执行Make_Path(v);
算法最后执行路径回到u.pai;
}
举个例子: