暑假训练 最短路径问题 HDU - 3790 最短路基础

题目描述:
给你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
code:

#include<cstdio>
#include<iostream>
#include<string.h>
#define inf 0x3f3f3f3f
using namespace std;

const int maxn = 1010;
struct node
{
    long long int len;
    long long int cost;
}nodes[maxn][maxn];
long long int m, n, a, b, d, p, s, t;
long long int dis[maxn], spend[maxn], book[maxn];
int main()
{
    while(cin>>n>>m && n && m)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                nodes[i][j].len = inf;
                nodes[i][j].cost = 0;
            }
            nodes[i][i].cost = 0;
            nodes[i][i].len = 0;
        }
        memset(dis, 0x3f, sizeof dis);
        memset(book, 0, sizeof book);
        for(int i = 1; i <= m; i++)
        {
            scanf("%lld%lld%lld%lld", &a, &b, &d, &p);
            if(nodes[a][b].len > d)
            {
                nodes[a][b].len = nodes[b][a].len = d;
                nodes[a][b].cost = nodes[b][a].cost = p;
            }
            else if(nodes[a][b].len == d && nodes[a][b].cost < p)
                nodes[a][b].cost = nodes[b][a].cost = p;
        }
        scanf("%lld%lld", &s, &t);
        for(int i = 1; i <= n; i++)
        {
            dis[i] = nodes[s][i].len;
            spend[i] = nodes[s][i].cost;
        }
        book[s] = 1;
      /*  for(int i = 1; i <= n; i++)
        {
            cout<<"a:"<<dis[i]<<"   "<<spend[i]<<endl;
        }  */
        for(int i = 1; i <= n-1; i++)
        {
            int minNode, min = inf;
            for(int j = 1; j <= n; j++)
            {
                if(book[j] == 0 && dis[j] < min)
                {
                    minNode = j;
                    min = dis[j];
                }
            }
            //cout<<"a: "<<min<<endl;
            book[minNode] = 1;
            for(int j = 1; j <= n; j++)
            {
                if(book[j]==0 && min+nodes[minNode][j].len < dis[j] || (min+nodes[minNode][j].len == dis[j] && spend[i]+nodes[minNode][j].cost < spend[j]))
                {
                    dis[j] = min+nodes[minNode][j].len;
                    spend[j] = spend[minNode]+nodes[minNode][j].cost;
                }
            }
        }
        printf("%lld %lld\n", dis[t], spend[t]);
    }
    return 0;
}

小结:题目和描述都很清楚,就是带权图求最短路,再次学习了求最短路的算法,感觉暑假学的并不很清楚,这次终于搞懂了。

  1. floyd算法,分别以每个点a[k]作为任两点a[i],a[j]的中间点,以此不断松弛,最终得到所有点间的最短路,时间复杂度为O(n³)。
  2. dijkstra算法,进行n-1次松弛,每次找出距起点最近的且未松驰过的点,然后以该点作为中间点进行松弛,最终求出其它各个顶点距起点的最短路,时间复杂度为O(n²),同时写法上也有邻接矩阵和邻接链表两种。
  3. bellman-ford算法,分别记录每条边的起点和终点,根据边的权值找出各个点距起点的最短路,时间复杂度O(n*m),同时可以找出图中是否含有负边,并且还可以优化时间复杂度。

至于这些算法的进阶使用,只有慢慢挖掘了,对了,这道题有个坑就是可能相同顶点间可能有多条边,输入时要进行判断,还有自己在网上看到的博客:
最短路算法1
最短路算法2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值