《P15803 [GESP202603 七级] 物流网络》

题目背景

对应的选择、判断题:试题 - GESP 202603 C++ 七级 - 洛谷有题

题目描述

一个物流网络由 n 个城市和 m 条双向公路组成。每条公路都有两个属性:

  • 运输费用 wi
  • 景观评分 bi

当一辆运输车从城市 1 运送货物到城市 n 时,需要支付经过道路的运输费用之和。

为了推广旅游线路,物流公司推出了一项优惠政策:在运输路径上,可以免除景观评分最高 的那条公路的运输费用。如果有多条公路的景观评分同为最大值,则只免除其中 一条 的费用。

请你计算,从城市 1 到城市 n 的最小运输费用。

输入格式

第一行两个整数 n,m,分别表示城市数量和公路数量。

接下来 m 行,每行四个整数 u,v,w,b,表示存在一条连接城市 u 和城市 v 的双向公路,其中 w 为运输费用,b 为景观评分。

输出格式

输出一个整数,表示从城市 1 到城市 n 的最小费用。

如果无法到达,输出 -1

输入输出样例

输入 #1复制

复制代码
3 3
1 2 10 5
2 3 20 6
1 3 100 1

输出 #1复制

复制代码
0

说明/提示

样例解释

路径 1→2→3:费用 10+20,最大美丽值 6(边 2−3)。免除 20,总花费 10。

路径 1→3:费用 100,最大美丽值 1(边 1−3)。免除 100,总花费 0。

数据范围

1≤n≤5000,1≤m≤5000,1≤w,b≤109。

代码实现:

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
const ll INF = 1e18;

struct RawEdge{
    int u,v; ll w,b;
};
struct Edge{
    int to; ll w;
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,m;
    cin >> n >> m;
    vector<RawEdge> es(m);
    for(int i=0;i<m;i++)
    {
        cin >> es[i].u >> es[i].v >> es[i].w >> es[i].b;
    }
    sort(es.begin(),es.end(),[](const RawEdge &a,const RawEdge &b){
        return a.b < b.b;
    });
    vector<vector<Edge>> g(n+1);
    ll ans = INF;
    vector<ll> dist1(n+1,INF), distn(n+1,INF);
    priority_queue<pli,vector<pli>,greater<pli>> q;

    auto dijk = [&](int s, vector<ll>&d)
    {
        fill(d.begin(),d.end(),INF);
        d[s]=0;
        q.push({0,s});
        while(!q.empty())
        {
            auto [dis,u]=q.top(); q.pop();
            if(dis>d[u])continue;
            for(auto &e:g[u])
            {
                int v=e.to; ll w=e.w;
                if(d[v]>d[u]+w)
                {
                    d[v]=d[u]+w;
                    q.push({d[v],v});
                }
            }
        }
    };

    int ptr=0;
    while(ptr<m)
    {
        int curB = es[ptr].b;
        int nxt=ptr;
        vector<RawEdge> batch;
        while(nxt<m && es[nxt].b == curB)
        {
            batch.push_back(es[nxt]);
            nxt++;
        }
        for(int i=ptr;i<nxt;i++)
        {
            int u=es[i].u,v=es[i].v; ll w=es[i].w;
            g[u].push_back({v,w});
            g[v].push_back({u,w});
        }
        ptr = nxt;
        dijk(1,dist1);
        dijk(n,distn);
        for(auto &e : batch)
        {
            int u=e.u, v=e.v; ll w=e.w;
            ll cost1 = dist1[u] + distn[v];
            ll cost2 = dist1[v] + distn[u];
            ll total = min(cost1,cost2);
            if(total < ans) ans = total;
        }
    }
    dijk(1,dist1);
    ans = min(ans, dist1[n]);
    if(ans >= INF) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
相关推荐
aqiu11111116 天前
【算法刷题】蓝桥杯/AtCoder:删除元素后的中位数问题(Symmetry / Median)
算法·蓝桥杯·排序·中位数
aqiu11111118 天前
【算法刷题】蓝桥杯:0星际争霸(大数比较 + 多关键字自定义排序)
算法·排序·自定义排序
aqiu11111122 天前
【算法刷题】蓝桥杯:怎么倒茶(贪心算法 + 结构体排序)
贪心·排序
OuO-222 天前
笔试强训 Day 43:kotori 和抽卡(二)、ruby 和薯条、循环汉诺塔
数学·前缀和·二分查找·动态规划·排序·滑动窗口·循环汉诺塔
Tisfy1 个月前
LeetCode 3731.找出缺失的元素:哈希 / 排序
算法·leetcode·哈希算法·排序·哈希表
Tisfy1 个月前
LeetCode 3016.输入单词需要的最少按键次数 II:排序(贪心)
linux·算法·leetcode·题解·贪心·排序·计数
Tisfy1 个月前
LeetCode 3517.最小回文排列 I:排序(Python两行版) / 计数(O(n)时间+O(C)空间+字符串原地修改)
c语言·python·leetcode·字符串·排序·计数排序·回文
txzrxz1 个月前
拓补排序讲解
c++·算法·图论·排序
汉克老师2 个月前
GESP2026年6月认证C++八级( 第三部分编程题(1、线网建设))精讲
c++·最小生成树·排序·kruskal·并查集·gesp8级