最短路径问题 迪杰斯特拉算法 加上一些小技巧

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 36106    Accepted Submission(s): 10554


 

Problem Description

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

 

 

Input

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

 

 

Output

输出 一行有两个数, 最短距离及其花费。

 

 

Sample Input

 

3 2 1 2 5 6 2 3 4 5 1 3 0 0

 

 

Sample Output

 

9 11

 

 

Source

浙大计算机研究生复试上机考试-2010年

 

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 36106    Accepted Submission(s): 10554


 

Problem Description

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

 

 

Input

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

 

 

Output

输出 一行有两个数, 最短距离及其花费。

 

 

Sample Input

 

3 2 1 2 5 6 2 3 4 5 1 3 0 0

 

 

Sample Output

 

9 11

 

 

Source

浙大计算机研究生复试上机考试-2010年

 

这道题我用了以优化的Floyd算法,一直超时,遂用迪杰斯特拉算法

 

 

当有多个路径相同时,输出花费最少的,那我们在更新low时加个判断就行了

    if(low[j]>low[pos]+map1[pos][j])
                {
                    low[j]=low[pos]+map1[pos][j];
                    low2[j]=low2[pos]+pre[pos][j];
                }
                else
                if(low[j]==low[pos]+map1[pos][j]&&low2[j]>low2[pos]+pre[pos][j])
                {
                    low2[j]=low2[pos]+pre[pos][j];
                }

 

源代码:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
int low[1001],low2[1001],map1[1001][1001],pre[1001][1001],n,vis[1001],sum1,sum2;
void DJS(int s,int e)
{
    
    int i,j;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
    {
        low[i]=map1[s][i];
        low2[i]=pre[s][i];
    }
    low[s]=0;
    low2[s]=0;
    vis[s]=1;
    int pos;
    
    for(i=1;i<n;i++)
    {
        int min=inf;
        for(j=1;j<=n;j++)
        {
            if(vis[j])
            continue;
            if(low[j]<min)
            {
                min=low[j];
                pos=j;
            }
        }
        
        vis[pos]=1;
        
        for(j=1;j<=n;j++)
        {
            if(!vis[j]&&map1[pos][j]!=inf)
            {
                if(low[j]>low[pos]+map1[pos][j])
                {
                    low[j]=low[pos]+map1[pos][j];
                    low2[j]=low2[pos]+pre[pos][j];
                }
                else
                if(low[j]==low[pos]+map1[pos][j]&&low2[j]>low2[pos]+pre[pos][j])
                {
                    low2[j]=low2[pos]+pre[pos][j];
                }
            }
            
        }
        
    }
    printf("%d %d\n",low[e],low2[e]);
    
}
int main()
{
    int m,i,j,s,e;
    int k1,k2,k3,k4;
    while(~scanf("%d%d",&n,&m),n||m)
    {
        memset(low,inf,sizeof(low));
        memset(pre,inf,sizeof(pre));
        for(i=0;i<=n;i++)
        {
            for(j=0;j<=n;j++)
            {
                map1[i][j]=map1[j][i]=inf;
                pre[i][j]=pre[j][i]=inf;
            }
        }
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&k1,&k2,&k3,&k4);
            if(k3<map1[k1][k2])
            {
                map1[k1][k2]=map1[k2][k1]=k3;
                pre[k1][k2]=pre[k2][k1]=k4;
            }
        }
        scanf("%d%d",&s,&e);
        DJS(s,e);
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值