最短路,分层图 1266

 

 对于这种有限制的最短路题,我们可以采用打表的思路,记录dis[i][j]是从源点到i点速度为j的最短时间,这就是分层图,将情况分类讨论

这种思路还可以处理这样的问题:我们可以最多让k条边的权值为0,求最短路,那么dis[i][j]就是记录从源点到i点用了j次使权值为0的最小边权和。

from queue import PriorityQueue


n,m,d=map(int ,input().split())
class node:
    def __init__(self,v,ne,l,t,p):
        self.v=v
        self.l=l
        self.t=t
        self.ne=ne
        self.p=p
line=[0]
cnt=0
h=[0 for i in range(200)]

for i in range(m):
    a,b,v,l=map(int ,input().split())
    if v==0:
        cnt+=1
        line.append(node(b,h[a],l,-1,-1))
        h[a]=cnt
    else :
        cnt+=1
        line.append(node(b,h[a],l,l/v,v))
        h[a]=cnt
inf=float("inf")
dis=[[inf for i in range(510)]for i in range(200)]
class node2:
    def __init__(self,u=inf,v=inf):
        self.v=v
        self.u=u
pre=[[node2() for i in range(510)]for i in range(200)]
vis=[[False for i in range(510)]for i in range(200)]
class node1:
    def __init__(self,u,t,v):
        self.t=t
        self.u=u
        self.v=v
    def __lt__(self, other):
        return self.t<other.t

def dj():
    q=PriorityQueue()
    dis[0][70]=0
    q.put(node1(0,0,70))
    while (q.qsize()):
        mm=q.get()
        ind=h[mm.u]
        uu=mm.u
        tt=mm.t
        while (ind!=0):
            vv=line[ind].v
            if (line[ind].t==-1):
                t=line[ind].l/mm.v
                if (dis[vv][mm.v]>t+tt):
                    dis[vv][mm.v]=t+tt
                    q.put(node1(vv,t+tt,mm.v))
                    pre[vv][mm.v]=node2(uu,mm.v)
            else:
                if (dis[vv][line[ind].p]>line[ind].t+mm.t):
                    dis[vv][line[ind].p] = line[ind].t + mm.t
                    q.put(node1(vv,line[ind].t + mm.t,line[ind].p))
                    pre[vv][line[ind].p] = node2(uu,mm.v)



            ind=line[ind].ne
dj()
minx=inf
ans=0
for i in range(510):
    if (dis[d][i]<minx):
        minx=dis[d][i]
        ans=i
aa=[]
def dfs(x,v):
    aa.append(x)
    if (x==0):

        return
    x1=pre[x][v].u
    v1=pre[x][v].v
    dfs(x1,v1)
dfs(d,ans)
while (aa):
    ans=aa.pop()
    if ans!=d:print(ans,end=" ")
    else: print(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值