HDU - 3790 最短路径问题

 

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


 

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年


大致题意: 这就是中文题意自己看

解题思路:我是用Dijkstra + 邻接矩阵 正常情况下邻接矩阵存的值是从A到B的距离  这里我将矩阵开为结构体  同时存距离和花费 dis数组同样开结构体 对于任意两点的距离 将起点S初始化为0就能求S到T的最短距离

 


#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define met(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e3 + 10;
int vis[MAXN];
using namespace std;

struct node //邻接矩阵结构体
{
    int len, cot;//长度 花费
}MAP[MAXN][MAXN];

struct disnode
{
    int len, cot;
}dis[MAXN];

struct Dijkstra
{
    void init()//初始化函数
    {
        met(vis, 0);
        met(MAP, 0x3f);
        met(dis, 0x3f);
        return ;
    }
    void add(int a, int b, int d, int p)//加边
    {
        if (MAP[a][b].len > d)
            { MAP[a][b].len = d; MAP[a][b].cot = p; }
        else if (MAP[a][b].len == d)
            MAP[a][b].cot = min(MAP[a][b].cot, p);
        MAP[b][a].len = MAP[a][b].len; //始终让MAP[a][b] == MAP[b][a]
        MAP[b][a].cot = MAP[a][b].cot;
        return ;
    }
    void dijkstra(int s, int n)//传入起点和总个数
    {
        dis[s].len = dis[s].cot = 0;
        for (int i = 1; i < n; i++)
        {
            int k, minn = INF;
            for (int j = 1; j <= n; j++)
            {
                if (!vis[j] && dis[j].len < minn)
                    { k = j; minn = dis[j].len; }
            }
            vis[k] = 1;
            for (int j = 1; j <= n; j++)
            {
                if (!vis[j] && dis[j].len > dis[k].len + MAP[k][j].len)//松弛操作  注意同时应更改距离和花费
                {
                    dis[j].len = dis[k].len + MAP[k][j].len;
                    dis[j].cot = dis[k].cot + MAP[k][j].cot;
                }
                else if (!vis[j] && dis[j].len == dis[k].len + MAP[k][j].len)//距离相等改花费
                {
                    if (dis[j].cot > dis[k].cot + MAP[k][j].cot)
                        dis[j].cot = dis[k].cot + MAP[k][j].cot;
                }
            }
        }
        return ;
    }
}Dj;

int main()
{
    int n, m;
    while (~scanf("%d %d", &n, &m) && (n + m))
    {
        Dj.init();//初始化
        for (int i = 0; i < m; i++)
        {
            int a, b, d, p;
            scanf("%d %d %d %d", &a, &b, &d, &p);//输入两点以及长度,花费
            Dj.add(a, b, d, p);
        }
        int s, t;
        scanf("%d %d", &s, &t);//输入起点 终点
        Dj.dijkstra(s, n);
       printf("%d %d\n", dis[t].len, dis[t].cot);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值