最短通路
题目描述
给定一个带权有向图,试求从顶点 s 到 t 的最短通路 保证输入数据中不存在重边,不存在自环,边权都大于 0 ,注意各数据的范围 本题目仅能使用python语言提交,请不要用其他语言,否则可能在汇总数据的时候视为无效
输入
第一行四个由空格隔开的整数 n (顶点个数), m (边数), s (起点), t (终点)组成; 之后的 m 行,每行三个正整数 a, b, c,表示一条从顶点 a 到顶点 b 长度为 c 的边。
输出
一共两行 第一行:路径,从源点到终点依次输出所经过得节点;第二行:一个整数,表示从 s 到 t 的最短路长度。数据保证仅一条通路。
Dijkstra算法 自然语言实现
设
v
0
v0
v0为源顶点,
W
e
i
g
h
t
s
Weights
Weights为顶点间权重数组(邻接矩阵),
S
w
e
i
g
h
t
Sweight
Sweight为
v
0
v0
v0到相应顶点最小权重数组,
S
p
a
t
h
Spath
Spath为最短路径数组,
w
f
o
u
n
d
wfound
wfound表示某顶点是否已确定最短路径(0未确定,1已确定),
有如下定义:
int Weigths[VNUM][VNUM],Spath[VNUM]={0};
int Sweight[VNUM],wfound[VNUM];
Dijkstra算法 C语言实现
void Dijkstra(int v0)
{
int i, j, v, minweight;
char wfound[VNUM] = {0}; //用于标记从v0到相应顶点是否找到最短路径,0未找到,1找到
for (i = 0; i < VNUM; i++)
{
Sweight[i] = Weights[v0][i];
Spath[i] = v0;
} //初始化数组Sweight和Spath
Sweight[v0] = 0;
wfound[v0] = 1;
for (i = 0; i < VNUM - 1; i++)
{ //迭代VNUM-1次
minweight = INF;
for (j = 0; j < VNUM; j++) //找到未标记的最小权重值顶点
if (!wfound[j] && (Sweight[j] < minweight))
{
v = j;
minweight = Sweight[v];
}
wfound[v] = 1; //标记该顶点为已找到最短路径
for (j = 0; j < VNUM; j++) //找到未标记顶点且其权值大于v的权值+(v,j)的权值,更新其权值
if (!wfound[j] && (minweight + Weights[v][j] < Sweight[j]))
{
Sweight[j] = minweight + Weights[v][j];
Spath[j] = v; //记录前驱顶点
}
}
}
Dijkstra算法 Python语言实现
对着C语言板子翻译的。
Weights=[[10000 for i in range(1000)] for j in range(1000)]
Spath=[0 for i in range(1000)]
Sweight=[0 for i in range(1000)]
wfound=[0 for i in range(1000)]
n,m,s,t=0,0,0,0
def Dijkstra(v0):
global Weights,Spath,Sweight,wfound,n,m,s,t
v=0
for i in range(1,n+1):
Sweight[i] = Weights[v0][i]
Spath[i] = v0
Sweight[v0] = 0
wfound[v0] = 1
for i in range(n-1):
minweight=10000
for j in range(1,n+1):
if wfound[j]==0 and (Sweight[j]<minweight):
v=j
minweight=Sweight[v]
wfound[v]=1
for j in range(1,n+1):
if wfound[j]==0 and (minweight + Weights[v][j] < Sweight[j]):
Sweight[j] = minweight + Weights[v][j]
Spath[j] = v
n,m,s,t=map(int,input().split())
for i in range (m):
a,b,c=map(int,input().split())
Weights[a][b]=c
Dijkstra(s)
ans=[]
i=t
while i!=s:
ans.append(i)
i=Spath[i]
ans.append(i)
ans.reverse()
for x in ans[0:-1]:
print(x,end=' ')
print(ans[-1])
print(Sweight[t])
关键通路
输入
第一行是四个由空格隔开的整数 n (节点个数), m (边数), s (源点), t (终点)。此后的 m 行,每行三个正整数 a, b, c, 表示一条从节点 a 到节点 b 的一条长度为 c 的边。(节点个数小于 15 个)
输出
第一行输出关键通路的长度;
第二行到第 n+1 行输出每一个顶点的 TE, TL 和缓冲时间;
最后一行按Hint中所给格式,输出所有的关键通路。(若有多条,则根据关键通路中节点的个数排序进行输出,长度相同则按字典序排)
输入样例
9 15 1 9
1 2 3
1 3 2
1 4 4
2 5 4
2 3 0
3 5 4
3 6 4
3 4 2
4 7 5
5 9 6
5 7 3
5 6 0
6 8 3
8 9 1
7 8 1
输出样例
Dis=13
Node 1: TE= 0 TL= 0 TL-TE= 0
Node 2: TE= 3 TL= 3 TL-TE= 0
Node 3: TE= 3 TL= 3 TL-TE= 0
Node 4: TE= 5 TL= 6 TL-TE= 1
Node 5: TE= 7 TL= 7 TL-TE= 0
Node 6: TE= 7 TL= 9 TL-TE= 2
Node 7: TE= 10 TL= 11 TL-TE= 1
Node 8: TE= 11 TL= 12 TL-TE= 1
Node 9: TE= 13 TL= 13 TL-TE= 0
[[1, 2, 5, 9], [1, 2, 3, 5, 9]]
实现思路
我非常的不会,这里讲的非常好。我是照着这个写的。
https://blog.csdn.net/been123456789jimmy/article/details/106515471
V=[[] for i in range (20)]
ETV=[0 for i in range(20)]
LTV=[]
indegree=[[0,0] for i in range(20)]
Q1=[]
Q2=[]
tmp=[0 for i in range(10)]
ans=[]
n,m,s,t=map(int,input().split())
def DFS(x,step):
if x==t:
ag=[]
ag.append(s)
for i in range(step):
ag.append(tmp[i])
ans.append(ag)
return
for (u,w) in V[x]:
if ETV[u]==LTV[u] and ETV[u]==ETV[x]+w:
tmp[step]=u
DFS(u,step+1)
for i in range(m):
a,b,c=map(int,input().split())
V[a].append((b,c))
indegree[b][0]=b
indegree[b][1]+=1
Q1.append(s)
while len(Q1)!=0:
x=Q1.pop()
Q2.append(x)
for (x1,x2) in V[x]:
indegree[x1][1]-=1
if indegree[x1][1]==0:
Q1.append(x1)
if(ETV[x1]<ETV[x]+x2):
ETV[x1]=ETV[x]+x2
LTV=[ETV[Q2[-1]] for i in range (20)]
Q2.pop()
while len(Q2)!=0:
x=Q2.pop()
for (x1,x2) in V[x]:
if LTV[x]>LTV[x1]-x2:
LTV[x]=LTV[x1]-x2
DFS(s,0)
sorted(ans, key = len)
print("Dis=", ETV[t], sep="")
for i in range(1,n+1):
print("Node",i, end="")
print(": TE= %3d" % (ETV[i]), sep="", end=" ")
print(" TL= %3d" % (LTV[i]), sep="", end=" ")
print(" TL-TE= ", LTV[i] - ETV[i], sep="")
print(ans)