最短通路 关键通路 python实现

最短通路

题目描述

给定一个带权有向图,试求从顶点 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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值