本文利用Kosaraju’s Two-Pass Algorithm 解决强连通子图问题。

   Kosaraju算法是求解有向图强连通分量(strong connected component)的三个著名算法之一(另两个算法为TarjanGabow),能在线性时间求解出一个图的强分量。三种算法具体的差别可参考:http://www.cppblog.com/koson/archive/2010/04/27/113694.html

   什么是强连通分量?在这之前先定义一个强连通性(strong connectivity)的概念:有向图中,如果一个顶点s到t有一条路径,t到s也有一条路径,即s与t互相可达,那么我们说s与t是强连通的。那么在有向图中,由互相强连通的顶点构成的分量,称作强连通分量。

步骤概要:

1:在该图的逆图上运行DFS,将顶点按照后序编号的顺序放入一个数组中(显然,这个过程作用在DAG上得到的就是一个拓扑排序);

2:在原图上,按第一步得出的后序编号的逆序进行DFS。也就是说,在第二次DFS时,每次都挑选当前未访问的结点中具有最大后序编号的顶点作为DFS树的树根。

python实现具体代码:

time, threading from collections import defaultdict sys.setrecursionlimit(3000000) threading.stack_size(2**27) # largest power of 2 that didn't give me an error, don't know what I needed source='SCC.txt' visited={} finish={} leader={} t=0 s=0 def init(G): visited.clear() finish.clear() leader.clear() for i in list(G.keys()): visited[i] = 0 finish[i] = 0 leader[i]=0 def getG(): G={} Grev={} fin=open(source) for line in fin: v1=int(line.split()[0]) v2=int(line.split()[1]) G.setdefault(v1,[]).append(v2) Grev.setdefault(v1,[]) Grev.setdefault(v2,[]).append(v1) fin.close() return G, Grev def time_excute(): start = time.clock() getG() spend = time.clock()-start return spend def dfs(G, i): global t #print(s) visited[i]=1 leader[i]=s for j in G[i]: if j in visited and visited[j]==0: visited[j]=1 dfs(G,j) t=t+1 finish[i]=t def dfs_loop(G): global t global s t=0 #number of nodes processed so far s=None #current source vertex for i in sorted(list(G.keys()),reverse=True): if i in visited and visited[i]==0: s=i dfs(G,i) def getKeys(G,index): i = 0 #for i in range(len(G)): s= list(G.keys()) #print(s) for i in range(len(s)): if i == index: #print(s[i]) return s[i] i+=1 return None def main(): print("load data时间:") begin = time.clock() g, grev=getG() print(time.clock()-begin) print("第一次根据grev初始化状态值的时间:") begin = time.clock() init(grev) print(time.clock()-begin) print("#################################") print("第一次defloop时间:") begin = time.clock() dfs_loop(grev) #THE FIRST LOOP ON REVERSE GRAPH print(time.clock()-begin) print("根据visited建立newgraph时间:") begin = time.clock() newGraph={} for i in list(g.keys()): temp=[] for x in g[i]: temp.append(finish[x]) newGraph[finish[i]]=temp print(time.clock()-begin) print("第二次根据newgraph初始化状态值的时间:") begin = time.clock() init(newGraph) print(time.clock()-begin) print("#################################") print() print("第二次defloop时间:") begin = time.clock() dfs_loop(newGraph) print(time.clock()-begin) print("leader数组排序的时间:") begin = time.clock() lst= sorted(leader.values()) print(time.clock()-begin) print("#################################") print("#################################") print("#################################") print() stat=[] pre=0 print("根据leader数组获取强连通分量数目的时间:") begin = time.clock() for i in range(0,len(newGraph)-1): if lst[i]!=lst[i+1]: stat.append(i+1-pre) pre=i+1 stat.append(len(newGraph)-pre) L= sorted(stat) L.reverse() print(time.clock()-begin) print("最大5个强连通分量的数目为:") print(L[0:5]) t1 = threading.Thread(target=main,args=()) # creates a thread to call my function scc(graph) begin = time.clock() t1.start() # start the scc thread t1.join() # and wait for it to finish print('总的时间消耗为:') print(time.clock() - begin)

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-02-24
  • 2021-08-09
  • 2021-07-13
  • 2021-07-22
  • 2021-07-06
  • 2021-08-18
猜你喜欢
  • 2019-05-27
  • 2021-09-12
  • 2021-11-02
  • 2021-06-16
  • 2022-12-23
  • 2022-12-23
  • 2021-08-22
相关资源
相似解决方案