Algorithms: Design and Analysis, Part 1

本次作业是算法课程中最难的一次。我想,除了算法之外,还牵涉到实现的问题。因为很多编程语言都无法处理极大次数的递归调用。

题目说明

Download the text file here. Zipped version here. (Right click and save link as)

The file contains the edges of a directed graph. Vertices are labeled as positive integers from 1 to 875714. Every row indicates an edge, the vertex label in first column is the tail and the vertex label in second column is the head (recall the graph is directed, and the edges are directed from the first column vertex to the second column vertex). So for example, the 11th row looks liks : "2 47646". This just means that the vertex with label 2 has an outgoing edge to the vertex with label 47646

Your task is to code up the algorithm from the video lectures for computing strongly connected components (SCCs), and to run this algorithm on the given graph.

Output Format: You should output the sizes of the 5 largest SCCs in the given graph, in decreasing order of sizes, separated by commas (avoid any spaces). So if your algorithm computes the sizes of the five largest SCCs to be 500, 400, 300, 200 and 100, then your answer should be "500,400,300,200,100". If your algorithm finds less than 5 SCCs, then write 0 for the remaining terms. Thus, if your algorithm computes only 3 SCCs whose sizes are 400, 300, and 100, then your answer should be "400,300,100,0,0".

WARNING: This is the most challenging programming assignment of the course. Because of the size of the graph you may have to manage memory carefully. The best way to do this depends on your programming language and environment, and we strongly suggest that you exchange tips for doing this on the discussion forums.

算法实现

算法的实现较为简单,分为三步,第一步求图的转置,第二步DFS遍历转置后的图,得到拓扑序列,第三步使用这个拓扑序列对图进行DFS,每次DFS得到的点即为一个SCC/强联通集合。

初步使用python实现的代码如下:

def firstdfs(vertexind):global fs,isexplored,visitordered,mapDictTif len(mapDictT[vertexind])>0:for ind in mapDictT[vertexind]:if not isexplored[ind-1]:isexplored[ind-1]=Truefirstdfs(ind)visitordered[fs-1]=vertexind#print(str(vertexind)+' fs: '+str(fs))fs=fs-1def seconddfs(vertexind):global s,secisexplored,header,mapDictif len(mapDict[vertexind])==0:returnfor ind in mapDict[vertexind]:if not secisexplored[ind-1]:secisexplored[ind-1]=Trueseconddfs(ind)header[s-1]+=1maplength=875714
#maplength=8
f=open('SCC.txt','r')
mapDict={x:[] for x in range(1,maplength+1)}
mapDictT={x:[] for x in range(1,maplength+1)}
for line in f.readlines():tmp=[int(x) for x in line.split()]mapDict[tmp[0]].append(tmp[1])mapDictT[tmp[1]].append(tmp[0])
f.closefs=maplength
isexplored=[False for x in range(1,maplength+1)]
secisexplored=[False for x in range(1,maplength+1)]
visitordered=[0 for x in range(1,maplength+1)]
header=[0 for x in range(1,maplength+1)]for ind in range(1,maplength+1):if not isexplored[ind-1]:#print('Begin from: '+str(ind))isexplored[ind-1]=Truefirstdfs(ind)
print('Second DFS')
for ind in visitordered:if not secisexplored[ind-1]:s=indsecisexplored[ind-1]=Trueseconddfs(ind)header.sort(reverse=True)
print(header[0:20])

用来测试的图存储在文本文件中,测试用文件内容如下:

1 2
2 6
2 3
2 4
3 1
3 4
4 5
5 4
6 5
6 7
7 6
7 8
8 5
8 7

注意,maplength测试时要改成8。输出的前五个应该是

3,3,2,0,0

Python的迭代次数限制

Python有默认的函数迭代次数限制,默认一般不超过1000,如果超过此次数会造成栈溢出错误。使用下列代码可以更改默认迭代限制并显示

import sys
sys.setrecursionlimit(80000000)
print(sys.getrecursionlimit())

使用下列代码可以测试实际能达到的迭代次数

def f(d):if d%500==0:print(d)f(d+1)
f*(1)

使用上述代码测试,更改限制后,win8系统下面python3.3内存8G最大迭代次数4000左右,debian6系统下python3.2内存16G最大迭代次数26000左右,内存均未耗尽。尽管次数限制放宽,但由于某些原因还是受到限制。这种情况下不会报告栈溢出错误,但程序同样会crash。

问题在哪里呢?到论坛看了一下别人的讨论,才明白还有可能栈size不够。

完善版本的程序

把栈size设置为64M之后就ok了。

完整代码如下:

import sys,threading
sys.setrecursionlimit(3000000)
threading.stack_size(67108864)def firstdfs(vertexind):global fs,isexplored,visitordered,mapDictTif len(mapDictT[vertexind])>0:for ind in mapDictT[vertexind]:if not isexplored[ind-1]:isexplored[ind-1]=Truefirstdfs(ind)visitordered[fs-1]=vertexind#print(str(vertexind)+' fs: '+str(fs))fs=fs-1def seconddfs(vertexind):global s,secisexplored,header,mapDictif len(mapDict[vertexind])==0:returnfor ind in mapDict[vertexind]:if not secisexplored[ind-1]:secisexplored[ind-1]=Trueseconddfs(ind)header[s-1]+=1def sccmain():global mapDict,mapDictT,fs,isexplored,visitordered,s,secisexplored,headermaplength=875714#maplength=11f=open('SCC.txt','r')mapDict={x:[] for x in range(1,maplength+1)}mapDictT={x:[] for x in range(1,maplength+1)}for line in f.readlines():tmp=[int(x) for x in line.split()]mapDict[tmp[0]].append(tmp[1])mapDictT[tmp[1]].append(tmp[0])f.closefs=maplengthisexplored=[False for x in range(1,maplength+1)]secisexplored=[False for x in range(1,maplength+1)]visitordered=[0 for x in range(1,maplength+1)]header=[0 for x in range(1,maplength+1)]for ind in range(1,maplength+1):if not isexplored[ind-1]:#print('Begin from: '+str(ind))isexplored[ind-1]=Truefirstdfs(ind)print('Second DFS')for ind in visitordered:if not secisexplored[ind-1]:s=indsecisexplored[ind-1]=Trueseconddfs(ind)header.sort(reverse=True)print(header[0:20])if __name__ =='__main__':thread=threading.Thread(target=sccmain)thread.start()

Algorithms Part 1-Question 4- SCC 强联通问题相关推荐

  1. CodeForces 1213F (强联通分量分解+拓扑排序)

    传送门 •题意 给你两个数组 p,q ,分别存放 1~n 的某个全排列: 让你根据这两个数组构造一个字符串 S,要求: (1)$\forall i \in [1,n-1],S_{pi}\leq S _ ...

  2. BZOJ 2140 稳定婚姻(强联通分量判环)【BZOJ修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2140 是 hydro 的 BZOJ ...

  3. [拓扑排序/强联通分量] [NOIP201402] 信息传递

    信息传递 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日 ...

  4. POJ 2186 popular cow 有向图的强联通问题 Tarjan算法

    参考:http://hi.baidu.com/1093782566/blog/item/e5a0e9229913bd048b82a175.html http://www.cppblog.com/Iro ...

  5. CodeForces - 1547G How Many Paths?(强联通缩点+拓扑)

    题目链接:点击查看 题目大意:给出一张有向图,无重边,有环,现在需要判断每个点和点 111 的关系: 000:点 111 无法到达点 uuu 111:点 111 到点 uuu 有且仅有一条路径 222 ...

  6. POJ 2762Going from u to v or from v to u?(强联通 + 缩点 + 拓扑排序)

    [题意]: 有N个房间,M条有向边,问能否毫无顾虑的随机选两个点x, y,使从①x到达y,或者,②从y到达x,一定至少有一条成立.注意是或者,不是且. [思路]: 先考虑,x->y或者y-> ...

  7. 强联通分量与双连通分量

    强联通分量 1.概念 在有向图G中,如果两点互相可达,则称这两个点强连通,如果G中任意两点互相可达,则称G是强连通图. 定理: 1.一个有向图是强连通的,当且仅当G中有一个回路,它至少包含每个节点一次 ...

  8. POJ 2186 Popular Cows (强联通分量)

    链接 :http://poj.org/problem?id=2186 一个联通分量里的所有的牛满足任何一个被其他牛认为是红人.强联通缩点之后 只需要找到一个且只有一个联通分量且它的出度为0 答案就是这 ...

  9. [HDOJ6165] FFF at Valentine(强联通分量,缩点,拓扑排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165 题意:问一个有向图中是否有任意两点可以到达. 读错题就彻底输了,读成判断是否有任意条路,使得经过 ...

最新文章

  1. 杀死本地80端口被占用的进程,还你一片宁静乐土
  2. 台湾大学林轩田机器学习基石课程学习笔记14 -- Regularization
  3. spring cloud: 使用consul来替换config server
  4. Python刷题-7
  5. AI 实战:GPS实景识别网络项目(源码共享)
  6. 最新安徽省二c语言题型_2020年成人高考考试考前1个月最新最全备考攻略+资料,考生必看,建议收藏!...
  7. Widows下TortoiseGit登录密码错误
  8. linux学习笔记:处理linux目录的常用命令
  9. 约会安排HDU - 4553
  10. php计算1000000以内的质数,1000000以内质数表
  11. docker学习笔记(四)使用docker搭建环境
  12. 基于单片机的危险气体泄露报警器设计
  13. axure 教务系统_【Axure原型推荐】第1期 在线教育小程序原型
  14. 无线充电的技术原理和发展现状
  15. mt4下载正版官网下载(如何分辨真假MT4软件)
  16. 新手:MySQL 左连接 右连接 内连接 全外连接查询数据
  17. 实验一段有趣的js代码。
  18. 文本议题分类及态度赋值分类
  19. android 尺寸转换 dp sp in mm pt px转换为int
  20. CCF 201903-3 损坏的RAID5(Python100分)

热门文章

  1. ios 重复引用 静态库_iOS项目引用静态库文件.a
  2. python目录名称无效怎么处理_Python目录和文件处理总结详解
  3. 【图像处理基础知识(python+openCV)】——目标检测
  4. 如何在参考文献中优雅地引用URL?How do you get nicely formatted URLs in the bibliography?
  5. 网络口协商_以太网端口协商原理
  6. python1011无标题_讲解:Python:COMP1011 Programming For The WebPython
  7. wcf html 界面,WCF数据转换为原始html而不是Json格式
  8. java 数据验证_Java 数据验证
  9. python打开文件报错无效序列_解决Python 写文件报错TypeError的问题
  10. python入门经典27版_【python】编程语言入门经典100例--27