题目传送门

题目大意

\(\qquad\)有一张有向图,可以有若干个起点,只有一个终点,求所有起点到终点的最短路中最短的一条,若所有起点都与终点不连通,则输出\(-1\)

解题思路

\(\qquad\)我们这题可以想出两个方面的思路:

\(\qquad\)\(1.\)我们可以设置虚拟源点\(S=0(这样编号不会与其他点冲突)\),连接\(S\)与所有的起点,边权都为\(0\),跑\(S\)到终点的最短路,这样最后得到的最短路就是题目所求

\(\qquad\)\(2.\)我们可以反向建图,然后跑从终点为源点的最短路,然后枚举所有起点,用全局变量\(res\)记录全局最小值。

为什么可以

\(\qquad\)因为虚拟源点\(S\)到所有起点的边权都为\(0\),所以从\(S\)开始不会改变最短路的长度,又因为它同时确保了原先作为起点的每个点都是可以出现在路径中的,所以我们用\(S\)做源点跑出来的最短路,就是所有起点到终点的最短路的最短的一条

\(\qquad\)此处,反向建图不做解释。

代码实现

这里提供四份代码

分别是

\(\qquad\)\(1.虚拟源点Dijkstra\)

\(\qquad\)\(2.虚拟源点SPFA\)

\(\qquad\)\(3.反向建图Dijkstra\)

\(\qquad\)\(4.反向建图SPFA\)

提醒:别忘记了初始化idx,清空邻接表和标记数组!!!

\(虚拟源点Dijkstra\)
#include <iostream>
#include <cstring>
#include <queue> using namespace std;
typedef pair<int, int> PII; const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn; void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
} void Dijkstra(int S)
{
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<> > heap;
dist[S] = 0, heap.push({0, S}); while (heap.size())
{
auto t = heap.top().second; heap.pop(); if (st[t]) continue ;
st[t] = true ; for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
heap.push({dist[j], j});
}
}
}
} int main()
{
while (~scanf("%d%d%d", &n, &m, &T))
{
vector<int> stops; idx = 0; memset(h, -1, sizeof h); while (m -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); //反向建图
} int S = 0;
scanf("%d", &stn);
while (stn -- )
{
int x;
scanf("%d", &x);
add(S, x, 0);
} Dijkstra(S); int res = dist[T];
if (res == INF) puts("-1");
else printf("%d\n", res);
} return 0;
}
\(2.虚拟源点SPFA\)
#include <iostream>
#include <cstring>
#include <queue> using namespace std;
typedef pair<int, int> PII; const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn; void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
} void spfa(int S)
{
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
queue<int> q; dist[S] = 0, st[S] = true, q.push(S); while (q.size())
{
auto t = q.front(); q.pop();
st[t] = false ; for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if (!st[j]) st[j] = true, q.push(j);
}
}
}
} int main()
{
while (~scanf("%d%d%d", &n, &m, &T))
{
vector<int> stops; idx = 0; memset(h, -1, sizeof h); while (m -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); //反向建图
} int S = 0;
scanf("%d", &stn);
while (stn -- )
{
int x;
scanf("%d", &x);
add(S, x, 0);
} spfa(S); int res = dist[T];
if (res == INF) puts("-1");
else printf("%d\n", res);
} return 0;
}
\(3.反向建图Dijkstra\)
#include <iostream>
#include <cstring>
#include <queue> using namespace std;
typedef pair<int, int> PII; const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn; void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
} void Dijkstra(int S)
{
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<> > heap;
dist[S] = 0, heap.push({0, S}); while (heap.size())
{
auto t = heap.top().second; heap.pop(); if (st[t]) continue ;
st[t] = true ; for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
heap.push({dist[j], j});
}
}
}
} int main()
{
while (~scanf("%d%d%d", &n, &m, &T))
{
vector<int> stops; idx = 0; memset(h, -1, sizeof h); while (m -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(v, u, w); //反向建图
}
scanf("%d", &stn);
while (stn -- )
{
int x;
scanf("%d", &x);
stops.push_back(x);
} Dijkstra(T); int res = INF;
for (auto i : stops) res = min(res, dist[i]);
if (res == INF) printf("%d\n", -1);
else printf("%d\n", res);
} return 0;
}
\(4.反向建图SPFA\)
#include <iostream>
#include <cstring>
#include <queue> using namespace std;
typedef pair<int, int> PII; const int N = 1010, M = 40010, INF = 0x3f3f3f3f;
int h[N], w[M], e[M], ne[M], idx;
int n, m, T, dist[N], st[N], stn; void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
} void spfa(int S)
{
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
queue<int> q; q.push(S), dist[S] = 0, st[S] = true ; while (q.size())
{
auto t = q.front(); q.pop();
st[t] = false ; for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if (!st[j]) q.push(j), st[j] = true ;
}
}
}
} int main()
{
while (~scanf("%d%d%d", &n, &m, &T))
{
vector<int> stops; idx = 0; memset(h, -1, sizeof h); while (m -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); //反向建图
} int S = 0;
scanf("%d", &stn);
while (stn -- )
{
int x;
scanf("%d", &x);
add(S, x, 0);
} spfa(S); int res = dist[T];
if (res == INF) puts("-1");
else printf("%d\n", res);
} return 0;
}

\(\color{Green}{Accepted!}\)

AcWing1137. 选择最佳线路的更多相关文章

  1. [大牛翻译系列]Hadoop(4)MapReduce 连接:选择最佳连接策略

    4.1.4 为你的数据选择最佳连接策略 已介绍的每个连接策略都有不同的优点和缺点.那么,怎么来判断哪个最适合待处理的数据? 图4.11给出了一个决策树.这个决策树是于论文<A Compariso ...

  2. 自动选择最佳特征进行分类-SVM (Halcon)

    HALCON12里的example,classify_pills_auto_select_features.hdev. 执行流程: 1.选取相关特征(本例选取color和region组的所有特征)(本 ...

  3. 企业如何选择最佳的SSL

    如果你的企业有意采购SSL,那么本文可以给一个很好的方向.在本文中,我们将先简要介绍SSL定义及其工作原理,并探讨目前各种可用的SSL证书类型以及企业如何选择最佳的SSL. SSL定义 SSL及传输层 ...

  4. Debian初识(选择最佳镜像发布站点加入source.list文件)

    选择最佳镜像发布站点加入source.list文件:netselect,netselect-apt “该将哪个Debian镜像发布站点加入source.list文件?”.有很多方法来选择镜像发布站点, ...

  5. R in action读书笔记(11)-第八章:回归-- 选择“最佳”的回归模型

    8.6 选择“最佳”的回归模型 8.6.1 模型比较 用基础安装中的anova()函数可以比较两个嵌套模型的拟合优度.所谓嵌套模型,即它的一 些项完全包含在另一个模型中 用anova()函数比较 &g ...

  6. 如何为应用选择最佳的FPGA(下)

    如何为应用选择最佳的FPGA(下) How to select an FPGA board? FPGA板的选择在很大程度上受FPGA本身的影响,也受整个板的特性和性能的影响.们已经在上面的章节中讨论了 ...

  7. 如何为应用选择最佳的FPGA(上)

    如何为应用选择最佳的FPGA(上) How To Select The Best FPGA For Your Application 在项目规划阶段,为任何一个项目选择一个FPGA部件是最关键的决策之 ...

  8. 选择最佳策略:简单的方式和globals()

    promos = [fidelity_promo, bulk_item_promo, large_order_promo] ➊ def best_promo(order): ➋ "" ...

  9. 分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践

    确定应用程序类型 在 Citus 集群上运行高效查询要求数据在机器之间正确分布.这因应用程序类型及其查询模式而异. 大致上有两种应用程序在 Citus 上运行良好.数据建模的第一步是确定哪些应用程序类 ...

  10. WebSphere应用服务器内存泄漏探测与诊断工具选择最佳实践

    内存泄漏是比较常见的一种应用程序性能问题,一旦发生,则系统的可用内存和性能持续下降:最终将导致内存不足(OutOfMemory),系统彻底宕掉,不能响应任何请求,其危害相当严重.同时,Java堆(He ...

随机推荐

  1. Netty 学习(六):创建 NioEventLoopGroup 的核心源码说明

    Netty 学习(六):创建 NioEventLoopGroup 的核心源码说明 作者: Grey 原文地址: 博客园:Netty 学习(六):创建 NioEventLoopGroup 的核心源码说明 ...

  2. C#-12 转换

    一 什么是转换 转换是接受一个类型的值并使用它作为另一个类型的等价值的过程. 下列代码演示了将1个short类型的值强制转换成byte类型的值. short var1 = 5; byte var2 = ...

  3. CentOS 7.9 安装 redis-6.2.0

    一.CentOS 7.9 安装 redis-6.2.0 1 下载地址:https://download.redis.io/releases/redis-6.2.0.tar.gz 2 安装gcc来进行编 ...

  4. 源码随想 String -> SoftReference

    源码随想 String -> SoftReference 2021年7月27日 15:38:14 今天实习时看 String的源码,发现其中的一个构造方法 public String(byte ...

  5. day09-1存储引擎

    存储引擎 1.基本介绍 基本介绍 MySQL的表类型由存储引擎(Storage Engines)决定,主要包括MyISAM.innoDB.Memory等 MySQL数据表主要支持六种类型,分别是:CS ...

  6. 详解ROMA Connect API 流控实现技术

    摘要:本文将详细描述API Gateway流控实现,揭开高性能秒级流控的技术细节. 1.概述 ROMA平台的核心系统ROMA Connect源自华为流程IT的集成平台,在华为内部有超过15年的企业业务 ...

  7. Annocation(注解)的使用示例

    示例一:生成文档相关的注解示例二:在编译时进行格式检查(JDK内置的三个基本注解)@Override: 限定重写父类方法, 该注解只能用于方法@Deprecated: 用于表示所修饰的元素(类, 方法 ...

  8. "一键重装系统软件"操作流程

    博主之前重装系统都是直接用win10系统更新里的重置系统(版本不会变化),和U盘重装电脑出厂映像(有各种品牌自带的软件,而且由于是出场版本,版本很低) 所以这次用"小白一键重装系统" ...

  9. AR人体姿态识别,实现无边界的人机交互

    近年来,AR不断发展,作为一种增强现实技术,给用户带来了虚拟和现实世界的融合体验.但用户已经不满足于单纯地将某件虚拟物品放在现实场景中来感受AR技术,更想用身体姿势来触发某个指令,达到更具真实感的人机 ...

  10. Vue前端框架基础+Element的使用

    前置内容: AJAX基础+Axios快速入门+JSON使用 目录 1.VUE 1.1 概述 1.2 快速入门 1.3 Vue指令 1.3.1 v-bind & v-model 指令 1.3.2 ...