题目传送门

题目大意

\(\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. 垃圾回收机制GC

    垃圾回收机制GC 我们已经知道,name = 'leethon'这一赋值变量的操作,是将变量与数据值相绑定. 而数据值是存储到内存中的,有时变量会重新赋值即绑定其他数据值,而使得原本的数据值无法通过变 ...

  2. 谣言检测(DUCK)《DUCK: Rumour Detection on Social Media by Modelling User and Comment Propagation Networks》

    论文信息 论文标题:DUCK: Rumour Detection on Social Media by Modelling User and Comment Propagation Networks论 ...

  3. [ZJOI2012] 灾难 题解

    爵士好提 Solution 定义\(u\)控制\(v\)当且仅当\(u\)死后\(v\)也会死 把图建出来,从食物向消费者连边 我们不难想到只能先处理食物,再处理消费者,所以先上个拓扑排序 想一想暴力 ...

  4. Kafka之概述

    Kafka之概述 一.消息队列内部实现原理 (1)点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除) 点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消 ...

  5. JavaWeb完整案例详细步骤

    JavaWeb完整案例详细步骤 废话少说,展示完整案例 代码的业务逻辑图 主要实现功能 基本的CURD.分页查询.条件查询.批量删除 所使用的技术 前端:Vue+Ajax+Elememt-ui 后端: ...

  6. 某OA系统需要提供一个假条审批的模块,如果员工请假天数小于3天,主任可以审批该请假条;如果员工请假天数大于等于3天,小于10天,经理可以审批;如果员工请假天数大于等于10天,小于30天,总经理可以审批

    某OA系统需要提供一个假条审批的模块,如果员工请假天数小于3天,主任可以审批该请假条:如果员工请假天数大于等于3天,小于10天,经理可以审批:如果员工请假天数大于等于10天,小于30天,总经理可以审批 ...

  7. jstl的使用 转发和重定向(做项目遇到的一些问题总结)

    文章目录 1.jstl的使用 2.转发和重定向 3.shiro 4.spring是什么? 5.对AOP的理解 6.标签通常和标签一起使用 7.springmvc中的form表单 7.1 form标签 ...

  8. python face_recognition安装及各种应用

    1.安装 首先,必须提前安装cmake.numpy.dlib,其中,由于博主所用的python版本是3.6.4(为了防止不兼容,所以用之前的版本),只能安装19.7.0及之前版本的dlib,所以直接p ...

  9. 8.DRF请求响应和api_view

    一.请求对象(Request objects)   DRF引入了一个扩展Django常规HttpRequest对象的Request对象,并提供了更灵活的请求解析能力 Request对象的核心功能是re ...

  10. Bitmap和byte[]的相互转换

    /// <summary> /// 将Bitmap转换为字节数组 /// </summary> /// <param name="width"> ...