通用汇点:有向图中入度 = |V| - 1,出度 = 0的点。即所有点都汇集到一个通用汇点。
关联矩阵(用M表示)示例:其中D为通用汇点
A B C D E
A 1 0 1 1 1
B 0 1 1 1 0
C 1 0 0 1 0
D 0 0 0 0 0
E 0 0 1 1 0
问题:如何在O(V)的时间下判断一个有向图是否存在通用汇点?
算法:
①取两个游标i=1,j=1。
②若M[i][j]=1,则i++。此时比i小的点不可能是通用汇点,因为通用汇点不可能有出度。
若M[i][j]=0,则j++。此时比j小的点(但不包括i)不可能是通用汇点,因为通用汇点不可能有出度。
③如果i<=N且j<=N,则一直循环下去。
④最后时刻,如果i<=N(同时j>N),则i是唯一可能的通用汇点。若i>N,则通用汇点不存在。
⑤检查可疑的i点是不是通用汇点,只需检查其特征M[i][k]=0,M[k][i(i≠k)]=1,做出判断即可。
伪代码:
复杂度分析:
最坏的情况下,找到可疑的通用汇点需要O(V)的时间:只能向下或向右走嘛,最多2V步。
判断可疑点究竟是不是通用汇点,同样需要O(V)的时间,判断一行和一列嘛,最多2V步。
总的时间复杂度:O(V)+O(V) = O(V),V为点的个数
空间复杂度:显然就是矩阵的空间,O(V²)
举例说明:还是用文章开头的那个矩阵作为实例。
A B C D E
A 1 0 1 1 1
B 0 1 1 1 0
C 1 0 0 1 0
D 0 0 0 0 0
E 0 0 1 1 0
首先,M[1][1]=1,说明A不是通用汇点,因此转向下一行;
M[2][1]=0,同样说明了A不是通用汇点;
继续往右找到第一个非0数M[2][2],则可判断B不是通用汇点;
随后,M[3][2]=0,说明A不是通用汇点;
M[3][3]=0,说明A~C(不包含C)不是通用汇点
M[3][4]=1,说明C不是通用汇点;
重点来了,向下寻找,发现M[4][4]=0,说明A~D(不含D)不是通用汇点;
向右寻找,M[4][5]=0,说明A~E(不含D)不是通用汇点,
j++,则j=N+1>N,循环结束。
随后,判断D到底是不是通用汇点,显然是的。
参考资料:https://blog.csdn.net/lhq_er/article/details/72834010
谢谢观看!