赞
踩
无向图:
在数据结构中的无向图通常使用邻接矩阵表示
无向图的邻接矩阵是对称矩阵,有向图的邻接矩阵不是对称矩阵。
共有5个顶点(nodes),7条边(vertices)
其邻接矩阵为:num_node*num_node,矩阵中的数值表示两个相连接的节点的边的权值
节点 | A | B | C | D | E |
A | 0 | 6 | inf | 1 | inf |
B | 6 | 0 | 5 | 2 | 2 |
C | inf | 5 | 0 | inf | 5 |
D | 1 | 2 | inf | 0 | 1 |
E | inf | 2 | 5 | 1 | 0 |
在无向图中寻找最短路径通常使用的是Dijkstra算法和Floyd算法。
Dijkstra算法:给定某个特定的起始顶点,找到从起始顶点到图中所有顶点的距离最小值(最短路径),其时间复杂度为O(num_node**2)。
Floyd算法:找到从图中的所有顶点到达任意顶点的最短路径,其时间复杂度为O(num_node**3)。
Dijkstra算法:其时间复杂度为O(n**2),其中n表示图中的节点个数
Dijkstra算法是基于两个列表的,分别是visited和unvisited
当前无向图中具有5个顶点。
假设是要找到从A到达所有节点最短的距离
在distance列表中找到所有unvisited列表中的节点所具有的最小distance值,发现是A距离最小(实际上就是初始节点/start node)
current_node=A
找到A在无向图中的邻居节点,发现是B,D。正好B,D都在unvisited列表中
distance[B]=min(distance(B),distance(A)+vertice(A,B))=min(float('inf'),0+6) =6 故更新distance列表中B的值
distance[D]=min(distance(D),distance(A)+vertice(A,D))=min(float('inf'),0+2)=1 故更新distance列表中D的值
将节点A从unvisted列表中删除,放到visited列表中
此时
visited=[A]
unvisited=[B,C,D,E]
distance[A,B,C,D,E]=[0,6,float(''inf),1,float(''inf)]
在distance列表中找到所有unvisited列表中的节点所具有的最小distance值,此时unvisted中是BCDE,则发现是D距离=1最小
current_node=D
找到D在无向图中的邻居节点,发现是A,B,E。A不在unvisited列表中,B,E在unvisited列表中。故不管A,只判断B,E
distance[B]=min(distance(B),distance(D)+vertice(D,B))=min(6,1+2) =3 故更新distance列表中B的值
distance[E]=min(distance(E),distance(D)+vertice(D,E))=min(float('inf'),1+1) =2 故更新distance列表中E的值
将节点D从unvisted列表中删除,放到visited列表中
此时
visited=[A,D]
unvisited=[B,C,E]
distance[A,B,C,D,E]=[0,3,float(''inf),1,2]
在distance列表中找到所有unvisited列表中的节点所具有的最小distance值,此时unvisted中是BCE,则发现是E距离=2最小
current_node=E
找到E在无向图中的邻居节点,发现是B,C,D。D不在unvisited列表中,B,C在unvisited列表中。故不管D,只判断B,C
distance[B]=min(distance(B),distance(E)+vertice(E,B))=min(3,2+2) =3 故不更新distance列表中B的值
distance[C]=min(distance(C),distance(E)+vertice(E,C))=min(float(''inf),2+5) =7 故更新distance列表中C的值
将节点E从unvisted列表中删除,放到visited列表中
此时
visited=[A,D,E]
unvisited=[B,C]
distance[A,B,C,D,E]=[0,3,7,1,2]
在distance列表中找到所有unvisited列表中的节点所具有的最小distance值,此时unvisted中是BC,则发现是B距离=4最小
current_node=B
找到E在无向图中的邻居节点,发现是A,C,D。A,D不在unvisited列表中,C在unvisited列表中。故不管A,D,只判断C
distance[C]=min(distance(C),distance(B)+vertice(B,C))=min(7,4+5) =7 故不更新 distance列表中C的值
将节点B从unvisted列表中删除,放到visited列表中
此时
visited=[A,D,E,B]
unvisited=[C]
distance[A,B,C,D,E]=[0,3,7,1,2]
在distance列表中找到所有unvisited列表中的节点所具有的最小distance值,此时unvisted中是C,则发现是C距离=7最小
current_node=C
找到E在无向图中的邻居节点,发现是B,E。B,E不在unvisited列表中,故不对任何节点的距离进行判断
将节点C从unvisted列表中删除,放到visited列表中
此时
visited=[A,D,E,B,C]
unvisited=[]
distance[A,B,C,D,E]=[0,3,7,1,2]
所输出的distance列表表示的就是:从起始节点A出发,到达无向图中每个节点的最短路径长度。
- '''
- 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,
- 要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
- 输入描述:
- 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。
- 最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
- (1<n<=1000, 0<m<100000, s != t)
- 输出描述:
- 输出 一行有两个数, 最短距离及其花费。
- 输入
- 3 2
- 1 2 5 6
- 2 3 4 5
- 1 3
- 0 0
- 输出
- 9 11
- 您的代码已保存
- 运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
- case通过率为90.91%
- 感谢
- https://www.bilibili.com/video/av38254646 讲的真的非常清楚
- '''
-
- if __name__=='__main__':
- line1=list(map(int,input().split()))
- num_node=line1[0]
- num_vertice=line1[1]
-
- no_direct_graph=[]
-
- for i in range(num_vertice):
- no_direct_graph.append(list(map(int,input().split())))
-
- start_end=list(map(int,input().split()))
-
- dict_graph={}
- for k in range(len(no_direct_graph)):#对于无向图中的每一条边
- for j in range(num_node):
- if no_direct_graph[k][0]==j+1:
- if j+1 not in dict_graph:
- dict_graph[j+1]=[no_direct_graph[k]]
- else:
- dict_graph[j + 1].append(no_direct_graph[k])
- elif no_direct_graph[k][1]==j+1:
- if j + 1 not in dict_graph:
- dict_graph[j + 1] = [[no_direct_graph[k][1],no_direct_graph[k][0],no_direct_graph[k][2],no_direct_graph[k][3]]]
- else:
- dict_graph[j + 1].append([no_direct_graph[k][1],no_direct_graph[k][0],no_direct_graph[k][2],no_direct_graph[k][3]])
- # print(dict_graph) 以字典的形式构造无向图
-
- visited=[]
- unvisited=[_+1 for _ in range(num_node)]
-
- distance=[float('inf') for _ in range(num_node)]
-
- money=[0 for _ in range(num_node)]
-
- temp=start_end[0]
- # money[temp - 1] = 0
- distance[temp-1]=0
- for j in range(num_node):
- temp_neighbor = dict_graph[temp]
- for route in temp_neighbor:
- # print('route',route)
- if route[1] not in visited: # 如果当前节点的邻居节点没有被访问过
- if distance[temp - 1] + route[2]<distance[route[1] - 1]:
- distance[route[1] - 1]=distance[temp - 1] + route[2]
- # print(route[-1])
- money[route[1] - 1]=money[temp-1]+route[-1]
- elif distance[temp - 1] + route[2]==distance[route[1] - 1]:#如果距离相等,取花费少的路径
- if money[temp-1]+route[-1]<money[route[1] - 1]:
- distance[route[1] - 1]=distance[temp - 1] + route[2]
- money[route[1] - 1] = money[temp - 1] + route[-1]
- # 找到money数组中除了当前temp的money值之外剩下的所有元素中最小money数量的位置,作为下一个temp位置
- distance_compare = distance.copy()
- distance_compare[temp - 1] = float("inf")
-
- visited.append(temp)
- if temp in unvisited:
- unvisited.remove(temp)
-
- min_value = float("inf")
- min_index = 0
-
- for k in range(num_node):
- if k+1 in unvisited:#如果当前的节点并没有被访问过
- if distance_compare[k] < min_value:
- min_value = distance_compare[k]
- min_index = k
- temp = min_index + 1
-
- print(distance[start_end[-1]-1],money[start_end[-1]-1])
-
- # min_distance=min(distance)
- # min_money=[]
- # for i,q in enumerate(distance):
- # if q==min_distance:
- # min_money.append(money[i])
- # print(min_distance,min(min_money))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。