单源最短路问题拓展


Description

给你一张图,图上有 n 个点,m 条边,要你找到两个点,使其最短路恰好包含给定的 k 个点。输出这条最短路的长度,输入保证有解。

输入格式

第一行两个数 n , m。表示有 n 个点,m 条边。

接下来 m 行每行三个数 xi, yi, vi, 表示有一条长度为vi的双向路径连接对应的两个点。

接下来一个数 k。

接下来一行 k 个数,表示一定要包含的点。

输出格式

一个数,符合要求的最短路长度。

样例输入

样例一

6 6

1 2 2

2 6 2

1 3 1

3 4 1

4 5 1

5 6 1

3

5 1 3

样例二

6 6

1 2 2

2 6 2

1 3 1

3 4 1

4 5 1

5 6 1

2

1 6

样例输出

样例一

3

样例二

4

数据范围:

对于30%的数据,1<=N<=10,1<=M<=20

对于60%的数据,1<=N<=500,1<=M<=1000。

对于100%的数据,1<=N<=100000,1<=M<=300000,1<=vi<=10000,1<=K<=N,保证有解。


题解

我们可以很容易地看出,对于满足要求的这条最短路的两个端点一定是属于要包含的点。因为如果不是,我们可以删掉这个端点,得到的解一定会更优。所以,如果我们找到了这两个端点,就可以很容易地求出答案。

那么我们如何找到这两个端点呢?根据题意,所有需要包含的点均在这条路径上,端点一定是其他点能到达的最远的点。所以我们任取一个包含的点,做一次单源最短路,找到离他最远的那个需要包含的点,这一定是一个端点。

我们再以这个端点做一次单源最短路,即可找到另一个端点。同时,另一个端点到此端点的距离已经求出了。所以一共只用做两遍单源最短路即可得出最后的答案。

代码

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
#define adde(u,v,w) {e[cnt] = (edge){v,w,head[u]};head[u] = &e[cnt++];} const int maxn = 1e5 + 5, maxm = 3e5 + 5;
const long long inf = 1e12;
int n,m,k;
long long dis[maxn];
int cnt;
int can[maxn];
bool inq[maxn]; queue<int>q; struct edge {
int v;
long long w;
edge *next;
}e[maxm * 2], *head[maxn]; int spfa(int s) {
while(!q.empty())q.pop();
for(int i = 1;i <= n;i++)dis[i] = inf,inq[i] = 0;
dis[s] = 0;
q.push(s);
inq[s] = 1;
while(!q.empty()) {
int u = q.front();q.pop();inq[u] = 0;
for(edge *k = head[u];k;k = k->next) {
if(dis[u] + k->w < dis[k->v]) {
dis[k->v] = dis[u] + k->w;
if(!inq[k->v]) {
inq[k->v] = 1;q.push(k->v);
}
}
}
}
int ans = 0,t = s;
for(int i = 0;i < k;i++)if(dis[can[i]] > ans) ans = dis[can[i]], t = can[i];
return t;
} int main() {
scanf("%d%d",&n,&m);
for(int i = 0;i < m;i++) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);adde(v,u,w);
}
scanf("%d",&k);
for(int i = 0;i < k;i++) {
int x;scanf("%d",&x);can[i] = x;
}
int t = spfa(can[0]);
t = spfa(t);
printf("%lld",dis[t]);
return 0;
}

最新文章

  1. java多线程实现方式
  2. 集合 LinkedList、ArrayList、Set、Treeset
  3. [nRF51822] 10、基础实验代码解析大全 &#183; 实验15 - RTC
  4. 关于box-shadow属性的一点心得
  5. JQuery实现列表中复选框全选反选功能封装
  6. java解析XML几种方式
  7. JDK源码阅读(二) AbstractList
  8. android如何让service不被杀死
  9. 嵌入式系统USB CDROM虚拟光驱驱动程序开发
  10. AFNetworking 保存Cookie Session 和 Webview 共享Cookie
  11. Windows卸载软件出现蓝屏SYSTEM SERVICE EXCEPTION(VrvProtect_x64_2.sys)
  12. 注册“Oracle Provider for OLE DB”和创建链接服务器
  13. VLAN的三种类型及三种属性
  14. 关于 SVN 项目检出
  15. 邓_Jquery测试题
  16. OxyPlot Controller OxyPlot控制器
  17. asp.net mvc session锁问题
  18. hive 远程管理
  19. 图的遍历算法:DFS、BFS
  20. 4.7 C++ dynamic_cast操作符

热门文章

  1. python基础——5(元组、字典、集合)
  2. 大数据学习——hdfs集群启动
  3. SPOJ FAVDICE 数学期望
  4. 数列分段Section II(二分)
  5. hdu 1728 逃离迷宫 [ dfs ]
  6. ibatis中的xml配置文件
  7. Xcode warning:Auto property synthesis will not synthesize property
  8. UVA 11827 Maximum GCD【GCD,stringstream】
  9. [NOI2012(bzoj2879)(vijos1726)]美食节 (费用流)
  10. MySQL事务及Spring事务管理