【洛谷】[最短路]P1629邮递员送信

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

//此题有坑点:可能有多条不同权值的重边,因为这道题无负权,所以不需要标记,也不可以标记
//解题思路:jijkstra裸题,有所不同的是还需要沿另一条路径回来而不是原路返回,则需要反向建图,得到返回时各点距离

const int maxn = 1e3 + 5;
const int maxm = 1e5 + 5;
inline int read()
{
    register int x = 0, f = 1;
    register char c = getchar();
    while(c > '9' || c < '0')
    {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
    {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}

struct edge
{
    int v, w;
};

//用的邻接表存图,其实这道题用邻接矩阵会更快也更方便些
//链式前向星存图当然也可以,但是感觉写起来稍麻烦
vector<edge> zp[maxn];
vector<edge> fp[maxn];

struct node
{
    int pos, dis;
//    重载运算符
    bool operator<(const node &rhs) const
    {
//        >时是最小堆,反之则为最大堆
        return dis > rhs.dis;
    }
};
//堆优化,查找最小距离点,降低时间复杂度
priority_queue<node> q;

int dis[maxn];
void dijkstra(int u, const vector<edge> *mp)
{
    memset(dis, 0x3f, sizeof(dis));
    q.push((node){u, 0});
    dis[u] = 0;
    while(!q.empty())
    {
        u = q.top().pos;
        int tdis = q.top().dis;
//        cout << tdis << " ";
        q.pop();
        for(int v, w, i = 0; i < mp[u].size(); i++)
        {
            v = mp[u][i].v;
            w = mp[u][i].w;
            if(tdis + w < dis[v])
            {
                dis[v] = tdis + w;
                q.push((node){v, dis[v]});
//                这道题不需要标记,因为会有重边
//                mark[v] = true;
            }
        }
    }
}

int main()
{
    int n = read(), m = read();
    for(int u, v, w, i = 1; i <= m; i++)
    {
        u = read(); v = read(); w = read();
        zp[u].push_back((edge){v, w});
        fp[v].push_back((edge){u, w});
    }
//    出发距离和
    dijkstra(1, zp);
    long long ans(0);
    for(int i = 2; i <= n; i++)
    {
        ans += dis[i];
    }
//    返回距离和
    dijkstra(1, fp);
    for(int i = 2; i <= n; i++)
    {
        ans += dis[i];
    }
    printf("%lld\n", ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值