├── .gitattributes ├── README.md ├── CodeCraft2020.py ├── CodeCraft2020_v1.py ├── CodeCraft2020_v3.py └── CodeCraft2020_v3_注释.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeCraft2020 2 | 一个简单的python版本:只能跑官方数据,100w貌似要跑很久,没提交过也不知道线上能不能跑。。 3 | 4 | 更新一个版本v1:加上了一个剪枝操作,100w数据跑了1分多钟。。 5 | 6 | 提交了一下,v1版本81分。。。 7 | 8 | 更新v3:找路径换成了6+1,线下100w48s,线上29s 9 | 10 | -------------------------------------------------------------------------------- /CodeCraft2020.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | # -------------------输入输出-------------------------- 5 | 6 | 7 | def readData(filename): 8 | data = [] 9 | f = open(filename) 10 | for line in f: 11 | line = list(map(int, line.split(','))) 12 | data.append(line) 13 | return data 14 | 15 | 16 | def writeFile(fileName, res, t1, t2): 17 | f = open(fileName, 'w') 18 | f.write(str(len(res))+'\n') 19 | for r in res: 20 | for i in range(len(r)-1): 21 | f.write(t1[r[i]]) 22 | f.write(t2[r[len(r)-1]]) 23 | 24 | # ------------------点编号转换为连续id--------------------- 25 | 26 | 27 | def convert(data): 28 | l = [] 29 | d = {} 30 | for line in data: 31 | l.append(line[0]) 32 | l.append(line[1]) 33 | st = list(set(l)) 34 | st.sort() 35 | for i in range(len(st)): 36 | d[st[i]] = i 37 | for i in range(len(data)): 38 | data[i][0] = d[data[i][0]] 39 | data[i][1] = d[data[i][1]] 40 | trans1 = [str(v)+',' for v in st] 41 | trans2 = [str(v)+'\n' for v in st] 42 | return trans1, trans2, data 43 | 44 | # -------------------建立邻接表----------------------------- 45 | 46 | 47 | def createGraph(data, n): 48 | g = [[] for i in range(n)] 49 | for line in data: 50 | g[line[0]].append(line[1]) 51 | for i in range(n): 52 | g[i].sort() 53 | return g 54 | 55 | # -------------------深度遍历找环-------------------------- 56 | 57 | 58 | def dfs(g, k, p_o, visit, res, path): 59 | for i in range(len(g[k])): 60 | if g[k][i] == p_o: # 如果下一个点是查询点,则找到了环 61 | if len(path) > 2: 62 | res.append(path.copy()) 63 | continue 64 | if visit[g[k][i]] == 1 or g[k][i] < p_o: # 如果下一个点是已经访问过的点,或者已经查询过的点 65 | continue 66 | if len(path) == 7: 67 | continue 68 | visit[g[k][i]] = 1 # 将下一个点设置为已访问,将点加入路径中 69 | path.append(g[k][i]) 70 | dfs(g, g[k][i], p_o, visit, res, path) # 访问下一个点 71 | path.pop() 72 | visit[g[k][i]] = 0 73 | 74 | 75 | if __name__ == "__main__": 76 | # -------------------输入--------------------------- 77 | data = readData('test_data.txt') 78 | t1, t2, data = convert(data) 79 | 80 | # --------------------处理---------------------------- 81 | n = len(t1) 82 | g = createGraph(data, n) 83 | visit = [0 for i in range(n)] 84 | path = [] 85 | res = [] 86 | for i in range(n): 87 | path.append(i) 88 | dfs(g, i, i, visit, res, path) 89 | path.pop() 90 | # if i % 100 == 0: 91 | # print(i) 92 | 93 | # ---------------------输出------------------------- 94 | print(len(res)) 95 | res.sort(key=lambda x: len(x)) 96 | writeFile('result.txt', res, t1, t2) 97 | -------------------------------------------------------------------------------- /CodeCraft2020_v1.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | # -------------------输入输出-------------------------- 5 | 6 | 7 | def readData(filename): 8 | data = [] 9 | f = open(filename) 10 | for line in f: 11 | line = list(map(int, line.split(','))) 12 | data.append(line) 13 | return data 14 | 15 | 16 | def writeFile(fileName, res, t1, t2): 17 | f = open(fileName, 'w') 18 | f.write(str(len(res))+'\n') 19 | for r in res: 20 | for i in range(len(r)-1): 21 | f.write(t1[r[i]]) 22 | f.write(t2[r[len(r)-1]]) 23 | 24 | # ------------------点编号转换为连续id--------------------- 25 | 26 | 27 | def convert(data): 28 | l = [] 29 | d = {} 30 | for line in data: 31 | l.append(line[0]) 32 | l.append(line[1]) 33 | st = list(set(l)) 34 | st.sort() 35 | for i in range(len(st)): 36 | d[st[i]] = i 37 | for i in range(len(data)): 38 | data[i][0] = d[data[i][0]] 39 | data[i][1] = d[data[i][1]] 40 | trans1 = [str(v)+',' for v in st] 41 | trans2 = [str(v)+'\n' for v in st] 42 | return trans1, trans2, data 43 | 44 | # -------------------建立邻接表----------------------------- 45 | 46 | 47 | def createGraph(data, n): 48 | g = [[] for i in range(n)] 49 | g1 = [[] for i in range(n)] 50 | for line in data: 51 | g[line[0]].append(line[1]) 52 | g1[line[1]].append(line[0]) 53 | for i in range(n): 54 | g[i].sort() 55 | g1[i].sort() 56 | return g, g1 57 | 58 | # -------------------深度遍历找环-------------------------- 59 | 60 | 61 | def dfs(g, k, p_o, visit, visit1, res, path): 62 | for i in range(len(g[k])): 63 | if g[k][i] == p_o: # 如果下一个点是查询点,则找到了环 64 | if len(path) > 2: 65 | res.append(path.copy()) 66 | # print(path) 67 | continue 68 | if visit[g[k][i]] == 1 or g[k][i] < p_o or visit1[g[k][i]] != p_o: # 如果下一个点是已经访问过的点,或者已经查询过的点 69 | continue 70 | if len(path) == 7: 71 | continue 72 | visit[g[k][i]] = 1 # 将下一个点设置为已访问,将点加入路径中 73 | path.append(g[k][i]) 74 | dfs(g, g[k][i], p_o, visit, visit1, res, path) # 访问下一个点 75 | path.pop() 76 | visit[g[k][i]] = 0 77 | 78 | # ----------------------剪枝操作----------------------------- 79 | 80 | 81 | def dfs1(g, k, p_o, visit, visit1, length): 82 | for i in range(len(g[k])): 83 | if g[k][i] < p_o or visit[g[k][i]] == 1: 84 | continue 85 | visit1[g[k][i]] = p_o 86 | if length == 3: 87 | continue 88 | visit[g[k][i]] = 1 89 | dfs1(g, g[k][i], p_o, visit, visit1, length+1) 90 | visit[g[k][i]] = 0 91 | 92 | 93 | if __name__ == "__main__": 94 | # -------------------输入--------------------------- 95 | data = readData('test_data.txt') 96 | t1, t2, data = convert(data) 97 | 98 | # --------------------处理---------------------------- 99 | n = len(t1) 100 | g, g1 = createGraph(data, n) 101 | visit = [0 for i in range(n)] 102 | visit1 = [-1 for i in range(n)] 103 | path = [] 104 | res = [] 105 | for i in range(n): 106 | path.append(i) 107 | dfs1(g, i, i, visit, visit1, 1) 108 | dfs1(g1, i, i, visit, visit1, 1) 109 | dfs(g, i, i, visit, visit1, res, path) 110 | path.pop() 111 | # if i % 100 == 0: 112 | # print(i) 113 | 114 | # ---------------------输出------------------------- 115 | print(len(res)) 116 | res.sort(key=lambda x: len(x)) 117 | writeFile('result.txt', res, t1, t2) 118 | -------------------------------------------------------------------------------- /CodeCraft2020_v3.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | # -------------------输入输出-------------------------- 5 | 6 | 7 | def readData(filename): 8 | data = [] 9 | f = open(filename) 10 | for line in f: 11 | line = list(map(int, line.split(','))) 12 | data.append(line) 13 | return data 14 | 15 | 16 | def writeFile(fileName, res, t1, t2): 17 | f = open(fileName, 'w') 18 | cnt = 0 19 | for r in res: 20 | cnt += len(r) 21 | f.write(str(cnt)+'\n') 22 | for rr in res: 23 | for r in rr: 24 | for i in range(len(r)-1): 25 | f.write(t1[r[i]]) 26 | f.write(t2[r[len(r)-1]]) 27 | 28 | # ------------------点编号转换为连续id--------------------- 29 | 30 | 31 | def convert(data): 32 | l = [] 33 | d = {} 34 | for line in data: 35 | l.append(line[0]) 36 | l.append(line[1]) 37 | st = list(set(l)) 38 | st.sort() 39 | for i in range(len(st)): 40 | d[st[i]] = i 41 | for i in range(len(data)): 42 | data[i][0] = d[data[i][0]] 43 | data[i][1] = d[data[i][1]] 44 | trans1 = [str(v)+',' for v in st] 45 | trans2 = [str(v)+'\n' for v in st] 46 | return trans1, trans2, data 47 | 48 | # -------------------建立邻接表----------------------------- 49 | 50 | 51 | def createGraph(data, n): 52 | g = [[] for i in range(n)] 53 | g1 = [[] for i in range(n)] 54 | for line in data: 55 | g[line[0]].append(line[1]) 56 | g1[line[1]].append(line[0]) 57 | for i in range(n): 58 | g[i].sort() 59 | g1[i].sort() 60 | return g, g1 61 | 62 | # -------------------深度遍历找环-------------------------- 63 | 64 | 65 | def dfs(g, k, p_o, visit, visit1, res, path): 66 | for i in range(len(g[k])): 67 | v = g[k][i] 68 | if v < p_o: 69 | continue 70 | if visit1[v] == -2 and visit[v] == 0: 71 | path.append(v) 72 | length = len(path) 73 | if length > 2: 74 | res[length-3].append(path.copy()) 75 | # print(path) 76 | path.pop() 77 | # continue 78 | if visit[v] == 1 or (visit1[v] != p_o and visit1[v] != -2): 79 | continue 80 | if len(path) == 6 or v == p_o: 81 | continue 82 | visit[v] = 1 # 将下一个点设置为已访问,将点加入路径中 83 | path.append(v) 84 | dfs(g, v, p_o, visit, visit1, res, path) # 访问下一个点 85 | path.pop() 86 | visit[v] = 0 87 | 88 | # ----------------------剪枝操作----------------------------- 89 | 90 | 91 | def dfs1(g, k, p_o, visit, visit1, length): 92 | for i in range(len(g[k])): 93 | if g[k][i] < p_o or visit[g[k][i]] == 1: 94 | continue 95 | visit1[g[k][i]] = p_o 96 | if length == 3: 97 | continue 98 | visit[g[k][i]] = 1 99 | dfs1(g, g[k][i], p_o, visit, visit1, length+1) 100 | visit[g[k][i]] = 0 101 | 102 | 103 | if __name__ == "__main__": 104 | # -------------------输入--------------------------- 105 | data = readData('/data/test_data.txt') 106 | t1, t2, data = convert(data) 107 | 108 | # --------------------处理---------------------------- 109 | n = len(t1) 110 | g, g1 = createGraph(data, n) 111 | visit = [0 for i in range(n)] 112 | visit1 = [-1 for i in range(n)] # 为-1则是被剪掉的点 113 | path = [] 114 | res = [[] for i in range(5)] 115 | for i in range(n): 116 | path.append(i) 117 | dfs1(g, i, i, visit, visit1, 1) 118 | dfs1(g1, i, i, visit, visit1, 1) 119 | for j in range(len(g1[i])): 120 | visit1[g1[i][j]] = -2 # 将倒数第二个点标记为-2 121 | dfs(g, i, i, visit, visit1, res, path) 122 | path.pop() 123 | for j in range(len(g1[i])): 124 | visit1[g1[i][j]] = i 125 | # if i % 100 == 0: 126 | # print(i) 127 | 128 | # ---------------------输出------------------------- 129 | print(len(res)) 130 | # res.sort(key=lambda x: len(x)) 131 | writeFile('/projects/student/result.txt', res, t1, t2) 132 | -------------------------------------------------------------------------------- /CodeCraft2020_v3_注释.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | # -------------------输入输出-------------------------- 5 | 6 | 7 | def readData(filename): 8 | data = [] 9 | f = open(filename) 10 | for line in f: 11 | line = list(map(int, line.split(','))) 12 | data.append(line) 13 | return data 14 | 15 | 16 | def writeFile(fileName, res, t1, t2): 17 | f = open(fileName, 'w') 18 | cnt = 0 19 | for r in res: 20 | cnt += len(r) 21 | f.write(str(cnt)+'\n') 22 | for rr in res: 23 | for r in rr: 24 | for i in range(len(r)-1): 25 | f.write(t1[r[i]]) 26 | f.write(t2[r[len(r)-1]]) 27 | 28 | # ------------------点编号转换为连续id--------------------- 29 | 30 | 31 | def convert(data): 32 | l = [] 33 | d = {} 34 | for line in data: 35 | l.append(line[0]) 36 | l.append(line[1]) 37 | st = list(set(l)) # 其实这儿求交集更好,懒得改了 38 | st.sort() # 排个序,输出就不用排序了 39 | for i in range(len(st)): 40 | d[st[i]] = i 41 | for i in range(len(data)): 42 | data[i][0] = d[data[i][0]] 43 | data[i][1] = d[data[i][1]] 44 | trans1 = [str(v)+',' for v in st] 45 | trans2 = [str(v)+'\n' for v in st] 46 | return trans1, trans2, data 47 | 48 | # -------------------建立邻接表----------------------------- 49 | 50 | 51 | def createGraph(data, n): 52 | g = [[] for i in range(n)] 53 | g1 = [[] for i in range(n)] # 反向图 54 | for line in data: 55 | g[line[0]].append(line[1]) 56 | g1[line[1]].append(line[0]) 57 | for i in range(n): 58 | g[i].sort() # 排序,为了输出有序 59 | g1[i].sort() 60 | return g, g1 61 | 62 | # -------------------深度遍历找环-------------------------- 63 | 64 | # 6+1思路:利用反向图标记可能成为环的倒数第一个点,再进行深度为6的搜索,搜索到被标记的点则成环。 65 | 66 | 67 | def dfs(g, k, p_o, visit, visit1, res, path): 68 | for i in range(len(g[k])): 69 | v = g[k][i] 70 | if v < p_o: # 小于查询点p_o的点都不用访问 71 | continue 72 | 73 | if visit1[v] == -2 and visit[v] == 0: # 当碰到倒数第一个点且这个点未被访问过,则找到一条路径 74 | path.append(v) # 把倒数第一个点加入路径中 75 | length = len(path) 76 | if length > 2: 77 | res[length-3].append(path.copy()) 78 | path.pop() 79 | 80 | if visit[v] == 1 or (visit1[v] != p_o and visit1[v] != -2): 81 | continue 82 | if len(path) == 6 or v == p_o: # 当搜索长度到6 或者 访问到查询点p_o就不继续访问了 83 | continue 84 | visit[v] = 1 # 访问v 85 | path.append(v) 86 | dfs(g, v, p_o, visit, visit1, res, path) 87 | path.pop() 88 | visit[v] = 0 # 退出v点,取消访问标记 89 | 90 | # ----------------------剪枝操作----------------------------- 91 | 92 | # 3邻域剪枝思路:如果将图看作是无向图,一个点数为7的环中,距离起点最远的点距离不超过3 93 | 94 | 95 | def dfs1(g, k, p_o, visit, visit1, length): 96 | for i in range(len(g[k])): 97 | if g[k][i] < p_o or visit[g[k][i]] == 1: # 1.小于查询点p_o的点都不用访问了; 2.当前查询中已经访问过的点不用再访问; 98 | continue 99 | # p_o为当前查找环的点,把距离p_o小于等于3的点标记为p_o(也可以标记为1,不过结束查询p_o点之后要,重新标记为-1) 100 | visit1[g[k][i]] = p_o 101 | if length == 3: 102 | continue 103 | visit[g[k][i]] = 1 104 | dfs1(g, g[k][i], p_o, visit, visit1, length+1) 105 | visit[g[k][i]] = 0 106 | 107 | 108 | if __name__ == "__main__": 109 | # -------------------输入--------------------------- 110 | data = readData('/data/test_data.txt') 111 | t1, t2, data = convert(data) 112 | 113 | # --------------------处理---------------------------- 114 | n = len(t1) 115 | g, g1 = createGraph(data, n) 116 | visit = [0 for i in range(n)] 117 | visit1 = [-1 for i in range(n)] # 确定3邻域 118 | path = [] 119 | res = [[] for i in range(5)] # 长度分别为3,4,5,6,7的路径 120 | for i in range(n): 121 | # --------------3邻域剪枝---------------------------------- 122 | # 分别遍历g,g1确定查询点i的3邻域 123 | # 把距离小于3的点的visit1标记为i,这样就确定了3邻域(不标记为1或者0是因为每次循环不用重新初始化visit1,为了省时间) 124 | dfs1(g, i, i, visit, visit1, 1) 125 | dfs1(g1, i, i, visit, visit1, 1) 126 | 127 | # --------------深度遍历找环-------------------------------- 128 | for j in range(len(g1[i])): 129 | # 将倒数第一个点(6+1)visit1标记为-2,其实可以新建一个visit2来标记的,要容易理解些。 130 | visit1[g1[i][j]] = -2 131 | 132 | path.append(i) 133 | dfs(g, i, i, visit, visit1, res, path) # 找查询点i的所有环 134 | path.pop() 135 | 136 | for j in range(len(g1[i])): 137 | visit1[g1[i][j]] = i # 清除visit1 "-2" 的标记 138 | 139 | # ---------------------输出------------------------- 140 | writeFile('/projects/student/result.txt', res, t1, t2) 141 | --------------------------------------------------------------------------------