hdu 3790. 最短路径问题

题目概述

解题思路

这道题显然是采用单源最短路径去求解,我采用的是Dijkstra算法。这道题相当于除了要维护各个节点到起点的最短路径长度,还要维护到起点的代价。

我首先采用的构图方法是:设置一个二维数组,第一维是节点数目,第二维是每个节点的邻接节点数目——

class Edges
{
    public:
        int val,
            dist,
            cost;
    Edges(int vi, int di, int ci): val(vi), dist(di), cost(ci) {}
};

我在每次碰到新的case的时候,都新建一个数组,用于维护每个节点与起点的最短路径长度。我们需要将该数组初始化为每个元素都是某个较大值。

接下来我发现,这种写法会碰到超时的情况:

我推测可能是在新建数组的时候花费了过长的时间,于是参照了博客中实现的思路,只生成一个数组,然后每次用memset去初始化它。

这种方法确实AC了,说明新建数组确实比较耗时。

方法性能

我的实现复杂度是O(V^2)。

代码示例

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<unordered_set>

int min_dist[1001];
int min_cost[1001];

class Edges
{
    public:
        int val, dist, cost;
        Edges(int vi, int di, int ci): 
        val(vi), dist(di), cost(ci) {};
};

using namespace std;

int main()
{
    int N, M;
    while(scanf("%d%d", &N, &M) && (N * M))
    {
        //construct graph
        vector<Edges> *Nodes = new vector<Edges> [N];
        int src, tgt, dis, cos;
        for (int mi = 0; mi < M;++mi)
        {
            scanf("%d%d%d%d", &src, &tgt, &dis, &cos);
            Nodes[src - 1].push_back(Edges(tgt, dis, cos));
            Nodes[tgt - 1].push_back(Edges(src, dis, cos));
        }
        scanf("%d%d", &src, &tgt);

        memset(min_dist, 0x3f, sizeof(min_dist));
        memset(min_cost, 0x3f, sizeof(min_cost));
        // int *min_dist = new int[N];
        // int *min_cost = new int[N];
        // for (int mi = 0; mi < N; ++mi)
        // {
        //     min_dist[mi] = 2147483647;
        //     min_cost[mi] = 2147483647;
        // }
        min_dist[src - 1] = 0;
        min_cost[src - 1] = 0;

        int cur_min, cur_idx, cur_cost;
        unordered_set<int> unvis;
        for (int ni = 0; ni < N; ++ni)
            unvis.insert(ni + 1);

        while(unvis.size())
        {
            //find shortest distance
            cur_min = cur_cost = 2147483647;
            for (unordered_set<int>::iterator iter = unvis.begin(); iter != unvis.end(); ++iter)
            {
                if(cur_min > min_dist[*iter - 1] || 
                cur_min == min_dist[*iter - 1] && cur_cost > min_cost[*iter - 1])
                {
                    cur_min = min_dist[*iter - 1];
                    cur_cost = min_cost[*iter - 1];
                    cur_idx = *iter - 1;
                }
            }

            //remove node
            unvis.erase(cur_idx + 1);
            min_dist[cur_idx] = cur_min;
            min_cost[cur_idx] = cur_cost;

            //update dist list
            for (int vi = 0, temp_len, temp_cos, temp_idx; vi < Nodes[cur_idx].size(); ++vi)
            {
                temp_idx = Nodes[cur_idx][vi].val - 1;
                temp_len = Nodes[cur_idx][vi].dist + cur_min;
                temp_cos = Nodes[cur_idx][vi].cost + cur_cost;
                if(temp_len < min_dist[temp_idx] || 
                (temp_len == min_dist[temp_idx] && temp_cos < min_cost[temp_idx]))
                {
                    min_dist[temp_idx] = temp_len;
                    min_cost[temp_idx] = temp_cos;
                }
            }

        }
        printf("%d %d\n", min_dist[tgt - 1], min_cost[tgt - 1]);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值