HDU-2544(最短路)——Dijkstra

最短路

Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
Sample Output
3
2

这里需要注意,由于是多组输入,每次min都应该重新赋值成无穷(INF),否则会出现错误。

C语言:
#include<stdio.h>
#define INF 0x3f3f3f3f 

int N,M;    //有N个结点,M条路 
int A,B,C;
int a[111][111];    //存放输入的数据 .a[x][y]=z 代表x→y需要花费的时间为z 
int dis[111];    // 存放x的最短路径.dis[x]=z 代表 1→x需要花费的最短时间为z 
int bj[111];    //判断x是否已经是永久标号了.bj[x]=1 代表已经是永久标号了,bj[x]=0则不是 

void dijkstra(int n)    //自定义dijkstra函数,求起点1到各点的最短时间(路径) 
{
    for(int u=1;u<=n;u++)
    {
        int k=1;
        for(int i=1;i<=n;i++)
        {
            int min=INF;
            for(int j=1;j<=n;j++)
            {
                if(bj[j]==0 && dis[j]<min)    //从不是永久标号的点中,寻找所需时间最短的结点 
                {
                    min=dis[j];
                    k=j;
                }
            }
            bj[k]=1;    //将找到的时间最短的结点变成永久标号
         
            for(int j=1;j<=n;j++)
            {
                if(bj[j]==0 && (dis[k]+a[k][j])<dis[j])    //更新最短时间变化但并不是此时找到的最短时间的结点 
                {
                    dis[j]=dis[k]+a[k][j];
                }
            }    
        }
    }
}

int main()
{
    while(~scanf("%d%d",&N,&M))
    {
        if(N==0 && M==0)    break;
        
        /*↓↓↓初始化↓↓↓*/ 
        for(int i=1;i<=N;i++) 
        {
            for(int j=1;j<=N;j++)
            {
                if(i==j)    a[i][j]=0;    //i与j相同时,i→j花费的时间为0 
                else    a[i][j]=INF;    //i与j不同时,i→j没有路,花费的时间为无穷 
            }
        }
        
        /*↓↓↓接收数据↓↓↓*/ 
        for(int i=1;i<=M;i++)
        {
            scanf("%d%d%d",&A,&B,&C);
            a[A][B]=a[B][A]=C;    //无向图,A→B和B→A要花费的时间均为C 
        }
        
        /*↓↓↓初始化↓↓↓*/ 
        for(int i=1;i<=N;i++)
        {
            dis[i]=a[1][i];        //由于起点在1,一开始i的最短时间为1→i 所需的时间,若1→i没有路则为无穷 
            bj[i]=0;    // 刚开始各点都不是永久标号 
        }
        bj[1]=1;    // 起点为1,因此1先成为永久标号 
        
        /*↓↓↓调用函数↓↓↓*/ 
        dijkstra(N);
        
        /*↓↓↓输出结果↓↓↓*/ 
        printf("%d\n",dis[N]);    
    }
}
python:
# -*- coding: utf-8 -*-
"""
Created on Mon May 18 00:38:53 2020

@author: 一脸呆滞
"""

INF=20000

def dijkstra(n,a,dis,bj):   #自定义dijkstra函数,求起点1到各点的最短时间(路径) 
    for u in range(1,n+1):
        k=1
        for i in range(1,n+1):
            Min=INF
            for j in range(1,n+1):
                if(bj[j]==0 and dis[j]<Min):    #从不是永久标号的点中,寻找所需时间最短的结点 
                    Min=dis[j]
                    k=j
            bj[k]=1	#将找到的时间最短的结点变成永久标号
            for j in range(1,n+1):
                if(bj[j]==0 and (dis[k]+a[k][j])<dis[j]):   #更新最短时间变化但并不是此时找到的最短时间的结点 
                    dis[j]=dis[k]+a[k][j]

def solve():
    N,M=map(int,input().split())    #有N个路口,共M条路
    if(N==0 and M==0):  #当输入两个0时结束循环
        return False
    #初始化
    a=[[0 for i in range(N+1)] for i in range(N+1)]
    dis=[[0 for i in range(N+1)] for i in range(N+1)]
    bj=[[0 for i in range(N+1)] for i in range(N+1)]
    for i in range(1,N+1):
        for j in range(1,N+1):
            if(i==j):
                a[i][j]=0   #i与j相同时,i→j花费的时间为0 
            else:
                a[i][j]=INF    #i与j不同时,i→j没有路,花费的时间为无穷 
    #接收数据
    for i in range(1,M+1):
        A,B,C=map(int,input().split())
        a[A][B]=a[B][A]=C	#无向图,A→B和B→A要花费的时间均为C 
    #初始化
    for i in range(1,N+1):
        dis[i]=a[1][i]  #由于起点在1,一开始i的最短时间为1→i 所需的时间,若1→i没有路则为无穷 
        bj[i]=0    #刚开始各点都不是永久标号 
    #调用函数
    dijkstra(N,a,dis,bj)
    #输出结果
    print(dis[N])
    return True
while(solve()): #while循环,直到solve返回False才结束循环
    1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值