试题编号: | 201709-4 |
试题名称: | 通信网络 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只能单向传递信息,即一条从部门a到部门b的通路只能由a向b传递信息。信息可以通过中转的方式进行传递,即如果a能将信息传递到b,b又能将信息传递到c,则a能将信息传递到c。一条信息可能通过多次中转最终到达目的地。 输入格式 输入的第一行包含两个整数N, M,分别表示部门的数量和单向通路的数量。所有部门从1到N标号。 输出格式 输出一行,包含一个整数,表示答案。 样例输入 4 4 样例输出 2 样例说明 部门1和部门4知道所有其他部门的存在。 评测用例规模与约定 对于30%的评测用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20;
|
60分代码(运行超时)
1.分析
明显这是一个图的问题,求经过每个点的路径数,很容易想到这是一个图的遍历问题,但是此题是单向图。所以我们解决问题的策略是对i点就行正向DFS、反向DFS,则经过i点的路径数为=正向DFS路径数+反向DFS路径数+1(1为自身节点i)
2.代码
n, m = list(map(int, input().split()))
edge_data = []
for i in range(m):
temp = list(map(int, input().split()))
edge_data.append(temp)
def initgraph(edge_data, node_num, inverse=False):
'''初始化图,图的表示方式如下:
graph = {1:[2,3], 2:[4], 3:[4], 4:[]}
参数解释:edge_data:键盘输入的数据组成的列表
node_num:节点数目
inverse:构建反向图的标识
'''
graph = {}
for i in range(1, node_num+1):
graph[i] = []
for d in edge_data:
if d[0] == i and inverse == False: # 构建正向图
graph[i].append(d[1])
elif d[1] == i and inverse == True: # 构建反向图
graph[i].append(d[0])
return graph
def dfs(graph, start):
'''
深度优先搜索,其中start为开始节点,
'''
num = 0 # 注意这里num应该为0,如果为1,则start节点正向DFS、反向DFS会计算2次
# 标记数组初始化
visited = {}
for key in graph.keys():
visited[key] = False
stack = [start]
visited[start] = True
while len(stack) != 0:
head = stack.pop(0)
for key in graph[head]:
if visited[key] == False:
stack.append(key)
visited[key] = True
num += 1
return num
graph = initgraph(edge_data, n) # 正向图
graph_inv = initgraph(edge_data, n, True) # 反向图
result = {}
for i in range(1, n+1):
num_1 = dfs(graph, i) # 对i节点正向DFS
num_2 = dfs(graph_inv, i) # 对i节点反向DFS
result[i] = num_1 + num_2 + 1 # 加1是本身
num = 0
for value in result.values():
if value >= n:
num+=1
print(num)