题目传送门

题目大意

\(\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. Qemu/Limbo/KVM镜像 Ubuntu 22.04 精简版,可运行Windows软件,内存占用不到200M

    镜像特征: Ubuntu 22.04系统 内置Wine 7.8,可运行大量Windows 软件 高度精简,内存占用仅200M不到. 自制UI,Windows3.1风格. 完全开源 镜像说明: 用户名为 ...

  2. Skywalking Swck Agent注入实现分析

    项目地址: GitHub - apache/skywalking-swck: Apache SkyWalking Cloud on Kubernetes 项目简介: A bridge project ...

  3. IDEA上关于 jstl导包的问题

    IDEA上关于 jstl的问题 在 IDEA上使用 maven创建 web骨架项目,在 pom文件中添加 jstl依赖 <dependency> <groupId>jstl&l ...

  4. hmtl5 web SQL 和indexDB

    前端缓存有cookie,localStorage,sessionStorage,webSQL,indexDB: cookie:有缺点 localStorage:功能单一 sessionStorage: ...

  5. 聊一聊被 .NET程序员 遗忘的 COM 组件

    一:背景 1.讲故事 最近遇到了好几起和 COM 相关的Dump,由于对 COM 整体运作不是很了解,所以分析此类dump还是比较头疼的,比如下面这个经典的 COM 调用栈. 0:044> ~~ ...

  6. File常用的方法操作、在磁盘上创建File、获取指定目录下的所有文件、File文件的重命名、将数据写入File文件

    文章目录 1.基本介绍 2.构造方法 3.常用的方法 4.代码实例 4.1 创建文件和目录(目录不存在) 4.1.1 代码 4.1.2 测试结果 4.2 测试目录存在的情况.直接写绝对的路径名 4.2 ...

  7. 齐博x1如何开启自定义标签模板功能

    为安全起见,同时也为了避免用户随意添加风格导致默认模板不协调,系统默认关闭了类似V系列的自定义修改模板功能.如下图所示,默认是关闭的 你如果需要启用的话,把下面的代码,参考下图导进去后,就可以增加一个 ...

  8. golang中的变量阴影

    索引:https://waterflow.link/articles/1666019023270 在 Go 中,在块中声明的变量名可以在内部块中重新声明. 这种称为变量阴影的原理很容易出现常见错误. ...

  9. SQL--临时表的使用

    临时表的创建 临时表分为:本地临时表和全局临时表 通俗区分: 本地临时表:只能在当前查询页面使用,新开的查询是不能使用它的     #temp 全局临时表:不管开多少查询页面都可以使用  ##temp ...

  10. Spring知识框架