【洛谷】P1342 请柬

该文描述了一个关于公交系统的最短路径问题,其中学生志愿者在各个公交站分发戏剧请柬。目标是计算从总部出发到所有站点,再返回的最小公交费用总和。文章提出利用Dijkstra算法两次寻找单源最短路径,一次正向,一次反向,以找到总的最小费用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目地址:

https://www.luogu.com.cn/problem/P1342

题目背景:
在电视时代,没有多少人观看戏剧表演。Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。

题目描述:
他们已经打印了请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。这里的公交系统是非常特殊的:共有 n n n个站点和 m m m个线路,所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。学生每天早上从总部所在的 1 1 1号站点出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。

输入格式:
输入的第一行是两个整数,代表站点个数 n n n和线路条数 m m m。第 2 2 2到第 ( m + 1 ) (m + 1) (m+1)行,每行三个整数 u , v , w u, v, w u,v,w,代表存在一条从 u u u出发到达 v v v的线路,费用为 w w w

输出格式:
输出一行一个整数,表示最小费用。

数据范围:
对于 100 % 100\% 100%的数据,保证:
1 ≤ n , m ≤ 1 0 6 1 \leq n, m \leq 10^6 1n,m106
1 ≤ u , v ≤ n 1 \leq u, v \leq n 1u,vn 1 ≤ w ≤ 1 0 9 1 \leq w \leq 10^9 1w109
1 1 1出发可以到达所有的站点。

即求 1 1 1为起点的单源最短路,为了求返回最短路,可以建立反向边再求一遍单源最短路。可以用两边Dijkstra算法来做。代码如下:

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

using ll = long long;
using PLI = pair<ll, int>;

const int N = 1e6 + 10;
int n, m;
int h[2][N], e[2][N], ne[2][N], w[2][N], idx[2];
bool vis[N];
ll dist[N];
priority_queue<PLI, vector<PLI>, greater<>> heap;

#define add(a, b, c, i)                                        \
  e[i][idx[i]] = b, ne[i][idx[i]] = h[i][a], w[i][idx[i]] = c, \
  h[i][a] = idx[i]++

ll dijkstra(int i) {
  memset(dist, 0x3f, sizeof dist);
  memset(vis, 0, sizeof vis);
  heap.push({0, 1});
  while (heap.size()) {
    auto t = heap.top(); heap.pop();
    ll d = t.first;
    int u = t.second;
    if (vis[u]) continue;
    vis[u] = true;
    dist[u] = d;
    for (int j = h[i][u]; ~j; j = ne[i][j]) {
      int v = e[i][j];
      if (!vis[v] && dist[v] > d + w[i][j]) {
        dist[v] = d + w[i][j];
        heap.push({dist[v], v});
      }
    }
  }

  ll res = 0;
  for (int i = 1; i <= n; i++) res += dist[i];
  return res;
}

int main() {
  scanf("%d%d", &n, &m);
  memset(h, -1, sizeof h);
  while (m--) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    add(a, b, c, 0), add(b, a, c, 1);
  }

  printf("%lld\n", dijkstra(0) + dijkstra(1));
}

时间复杂度 O ( m log ⁡ n ) O(m\log n) O(mlogn),空间 O ( n + m ) O(n+m) O(n+m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值