第k短路

Description

一天,HighLights实在是闲的不行,他选取了n个地点,n各地点之间共有m条路径,他想找到这m条路径组成的第k短路,你能帮助他嘛?

Input 第一行三个正整数,地点的数量n(2 <= n <= 2e5),边的数量m(1 <= m <= 2e5),k(1 <= k <=

min(m, 200))。

接下来m行,每行三个整数,边的一个顶点u(1<=u<=n),边的另一个顶点v(1<=v<=n),边的权值w(1<=w<=1e5),代表u有一条到v权值为w的单向边。

Output 输出第k短路的权值。

Output

Sample Input 1
4 4 3
1 3 27
1 4 16
1 2 15
2 4 3
Sample Output 1
16

思路

  • 这一题的前k短路径 是 m 条边组成的所有路径中选则前 第k短的路径(哎,,当时没有读好题),由于所给的 k的取值范围小于 m (但是给 n、m的范围都特别大。。),所以我们要求的前 第k条路经一定出现在 ,把 m 条路经按权值从小到大排序后,取前 k 条边 组成的 子图 中的第k短路径。。这样由于 k 比较小,那么选取的边的数量 就比较小,构成的子图规模就小,然后再把这个 子图 用 Ford算法跑一边,求出任意点最短路径,最后把所有路径 排一下序,取第k个就是答案了,,,,,,但是还有一点操作要注意,,那就是排序完后组成前k条边的节点编号 可能是很大的,我们需要用 set或map容器 重新定义一下编号。。(否则由于某些节点编号过大 存放子图的 二维数组 就没开出来)



    来张图,描述启发搜索过程。。。。。。。。。。。。。

代码

#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
using namespace std; #define INF 0x3f3f3f3f
const int maxn = 2e5 + 5;
const int maxm = 1e3 + 5;
struct Edge
{
int u,v,w;
bool operator < (const Edge & a) const
{
return w < a.w;
} } edge[maxn]; int G[maxm][maxm];
set<int> st;
map<int, Edge> mp; int main()
{
//freopen("T.txt","r",stdin);
int n,m,k;
scanf("%d %d %d", &n, &m, &k);
//取出前k小边
for(int i = 1; i <= m; i ++)
scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].w);
sort(edge + 1, edge + 1 + m);
//对出现在 前k小的边进行重新编号
for(int i = 1; i <= k; i ++)
{
st.insert(edge[i].u);
st.insert(edge[i].v);
}
int len = 0;
int id[maxn]; //转化 id 用到的
for(auto x : st)
id[x] = ++ len; //初始化、建前k条边组成的子图
for(int i = 1; i <= len; i ++)
for(int j = 1; j <= len; j ++)
if(i == j) G[i][j] = 0;
else G[i][j] = INF; for(int i = 1; i <= k; i ++)
G[id[edge[i].u]][id[edge[i].v]] = edge[i].w; //ford 算法
for(int mid = 1; mid <= len; mid ++)
for(int i = 1; i <= len; i ++)
for(int j = 1; j <= len; j ++)
G[i][j] = min(G[i][j], G[i][mid] + G[mid][j]);
int res[maxm];
int t = 0;
for(int i = 1; i <= len; i ++)
for(int j = 1; j <= len; j ++)
{
if(i == j) continue;
if(G[i][j] == INF) continue;
res[t ++] = G[i][j];
}
sort(res, res + t);
printf("%d", res[k - 1]);
return 0;
}

Remmarguts’ Date(第K短路 正版)

Time Limit: 4000MS Memory Limit: 65536K Total Submissions:

43103 Accepted: 11901 Description

“Good man never makes girls wait or breaks an appointment!” said the

mandarin duck father. Softly touching his little ducks’ head, he told

them a story.

“Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom.

One day their neighboring country sent them Princess Uyuw on a

diplomatic mission.”

“Erenow, the princess sent Remmarguts a letter, informing him that she

would come to the hall and hold commercial talks with UDF if and only

if the prince go and meet her via the K-th shortest path. (in fact,

Uyuw does not want to come at all)”

Being interested in the trade development and such a lovely girl,

Prince Remmarguts really became enamored. He needs you - the prime

minister’s help!

DETAILS: UDF’s capital consists of N stations. The hall is numbered S,

while the station numbered T denotes prince’ current place. M muddy

directed sideways connect some of the stations. Remmarguts’ path to

welcome the princess might include the same station twice or more than

twice, even it is the station with number S or T. Different paths with

same length will be considered disparate. Input

The first line contains two integer numbers N and M (1 <= N <= 1000, 0

<= M <= 100000). Stations are numbered from 1 to N. Each of the

following M lines contains three integer numbers A, B and T (1 <= A, B

<= N, 1 <= T <= 100). It shows that there is a directed sideway from

A-th station to B-th station with time T.

The last line consists of three integer numbers S, T and K (1 <= S, T

<= N, 1 <= K <= 1000). Output

A single line consisting of a single integer number: the length (time

required) to welcome Princess Uyuw using the K-th shortest path. If

K-th shortest path does not exist, you should output “-1” (without

quotes) instead. Sample Input

2 2
1 2 5
2 1 4
1 2 2
Sample Output 14
Source

启发搜索传送门

思路

  • 这一题才是我想错了的 前k短路径,它要求是 从出发点 s-> 到 终点e 经过 单向边(路可以重复走。。)的所有路径中 第k短的路径是多长。。。。。。
  • 解决这一题,我们可以用 启发搜索(使用这个方法主要是因为 他可以比避免 许多没有用的搜索,这样在数据量大的时候 也能过题),,其实我觉得它就是bfs的优化版,,,用这个方法来搜索 我们所需要的路径,对于 这个搜索重要的就是这个表达式子:fx = gx + hx, hx是我们的启发函数:而对应这一题,启发函数所确定的每一个节点到 终点e 的预估距离,我们可以 通过 Spfa算法 以终点e 作为起点,并把所有的边 逆过来跑一边,这就能求出 每个节点到终点的最短距离 hx了 ,gx是 起点s到 当前图中的某个节点的最短距离(这个距离是在搜索的过程 根据 边权值 来求),那么我们 启发搜索的所需 fx 就可求出来了。。。。,那么重要的是为神马这个方法,求出来的是的第 k 短路径的是准确的,我们可以这样考虑:随着搜索的不断过程,我们不短选取小的 fx小的点作为起点 放入优先级队列,我们要考虑,某个点的第k短的路径,由于是优先级队列 那么 fx(从s到e的距离)小的总是排在前边,先出优先级队列 终点是e的节点,我们只要 取第k个出队列,且终点是e的节点 答案则是我们所需要的。。。。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std; #define INF 0x3f3f3f3f
const int maxn = 1005;
const int maxm = 1e5 + 5; struct Edge
{
int v,w,next;
} edge[maxm], redge[maxm];
int head[maxm], rhead[maxm], dis[maxn];
int n, m, s, e, k;
int x, y; struct A
{
int pos,fx,gx;
bool operator < (const A& a) const //从小到大排序
{
if(fx == a.fx)
return gx > a.gx;
return fx > a.fx;
}
} st, ed; void Add(int u, int v, int w)
{
edge[++ x] = (Edge){ v, w, head[u]};
head[u] = x;
//逆向存图
redge[++ y] = (Edge){ u, w, rhead[v]};
rhead[v] = y;
} void Spfa(int s)
{
int mark[maxm];
for(int i = 1; i <= n; i ++)
dis[i] = INF,mark[i] = 0;
dis[s] = 0;
queue<int> q;
q.push(s);
int u,v,w;
while(! q.empty())
{
u = q.front(); q.pop();
mark[u] = 0; for(int i = rhead[u]; i != -1; i = redge[i].next)
{
v = redge[i].v;
w = redge[i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if(! mark[v])
{
q.push(v);
mark[v] = 1;
}
}
}
}
}
//启发搜索
int A_star(int s, int e, int k)
{
if(s == e) k ++;
if(dis[s] == INF) return -1;
priority_queue<A> q;
q.push( (A){ s, dis[s], 0});
int cnt = 0;
while(! q.empty())
{
st = q.top(); q.pop(); if(st.pos == e) cnt ++;
if(cnt == k) return st.gx; for(int i = head[st.pos]; i != -1; i = edge[i].next)
{
ed.pos = edge[i].v;
ed.gx = st.gx + edge[i].w;
ed.fx = ed.gx + dis[edge[i].v];
q.push(ed);
}
}
return -1;
} void init()
{
x = 0; y = 0;
// memset(head, -1, sizeof(head));
// memset(rhead, -1, sizeof(rhead));
for(int i = 0; i <= n; i ++)
head[i] = -1, rhead[i] = -1;
} int main()
{
//freopen("T.txt","r",stdin);
int u, v, w;
while(scanf("%d %d", &n, &m) != EOF)
{
init();
for(int i = 1; i <= m; i ++)
{
scanf("%d %d %d", &u, &v, &w);
Add(u, v, w);
}
cin >> s >> e >> k;
Spfa(e);
printf("%d\n", A_star(s, e, k));
} return 0;
}

多源第k短路 (ford + 重新定义编号) / 出发点、终点确定的第k短路 (Spfa+ 启发搜索)的更多相关文章

  1. hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。

    /** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...

  2. 以K个为一组反转单链表,最后不足K个节点的部分也反转

    package StackMin.ReverseList_offer16; public class ReverseKgroup_extend_offer16 { /** * 分组反转单链表,最后不足 ...

  3. php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干)

    php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干) 一.总结 1.仔细分析题干,找出要点:该递归还是得递归啊 2.短路求值原理:&&就是逻辑与,逻辑与有 ...

  4. HDU 3440 House Man(编号排序+线性差分约束跑最短路)

    House Man Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  5. IC开短路测试(open_short_test),编程器测试接触不良、开短路

    http://kitebee.meibu.com/forum.php?mod=viewthread&tid=69654&extra=page%3D5 IC开短路测试(open_shor ...

  6. CodeForces - 449B 最短路(迪杰斯特拉+堆优化)判断最短路路径数

    题意: 给出n个点m条公路k条铁路. 接下来m行 u v w      //u->v 距离w 然后k行 v w         //1->v 距离w 如果修建了铁路并不影响两点的最短距离, ...

  7. 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中

    转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比 ...

  8. Codeforces 61E Enemy is weak 乞讨i&lt;j&lt;k &amp;&amp; a[i]&gt;a[j]&gt;a[k] 对数的 树阵

    主题链接:点击打开链接 意大利正在寻求称号 i<j<k && a[i]>a[j]>a[k] 的对数 假设仅仅有2元组那就是求逆序数的做法 三元组的话就用一个树状 ...

  9. [Swift]LeetCode857. 雇佣 K 名工人的最低成本 | Minimum Cost to Hire K Workers

    There are N workers.  The i-th worker has a quality[i] and a minimum wage expectation wage[i]. Now w ...

随机推荐

  1. 从0开始搭建kafka客户端

    上一节,我们实现了搭建kafka集群.本节我们将从0开始,使用Java,搭建kafka客户端生产消费模型. 1.创建maven项目2.kafka producer3.kafka consumer4.结 ...

  2. Chromium的无锁线程模型C++代码示例

    引言 作者:程序员bingo,主要关注客户端架构设计.性能优化.崩溃处理,有多年的Chromium浏览器开发经验. 多线程一直是软件开发中最容易出问题的环节,很多的崩溃.卡死问题都与多线程有关.在常用 ...

  3. DBA_Oracle DBA常用表汇总(概念)--转载

    https://www.cnblogs.com/eastsea/p/3799411.html  一.与权限相关的字典 ALL_COL_PRIVS表示列上的授权,用户和PUBLIC是被授予者 ALL_C ...

  4. C# Socket编程实现简单的局域网聊天器

    目录 前言 编码 服务端监听接口 客户端连接接口 文字发送接口 文件发送接口 信息接收接口(文字与文件) 使用 注意事项 源码 前言 最近在学习C# Socket相关的知识,学习之余,动手做了一个简单 ...

  5. Top命令你最少要了解到这个程度

    top命令几乎是每个程序员都会用到的Linux命令.这个命令用来查看Linux系统的综合性能,比如CPU使用情况,内存使用情况.这个命令能帮助我快速定位程序的性能问题. 虽然这个命令很重要,但是之前对 ...

  6. 一些Nmap NSE脚本推荐

    前言 Nmap是一款强大的开源扫描工具.同时Nmap提供了强大的脚本引擎(Nmap Scripting Engine),支持通过Lua脚本语言来扩展Nmap的功能,在Nmap的发行版中已经包含了数百个 ...

  7. matplotlib 的几种柱状图

    1.x 表示数量,y 表示名字 import matplotlib.pyplot as plt dic = {'a': 22, 'b': 10, 'c': 6, 'd': 4, 'e': 2, 'f' ...

  8. 渗透测试-IP相关知识整理

    IP地址: 英文名称为Internet Protocol Address,是指互联网协议地址又称为网际协议地址.IP地址是Ip协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台机器分配一个 ...

  9. java常用容器简要性能分析(List。Map。Set)

    嗯,实习的时候看到这个,感觉蛮好,这里摘录学习,生活加油: 我曾经害怕别人嘲笑的目光,后来,发现他们的目光不会在我身上停留太久,人们更愿意把目光放在自己身上. 知乎上看到,讲给自己. List Lis ...

  10. IOS(苹果手机)使用video播放HLS流,实现在内部播放及全屏播放(即非全屏和全屏播放)。

    需求: 实现PC及移动端播放HLS流,并且可以自动播放,在页面内部播放及全屏播放功能. 初步:PC及安卓机使用hls.js实现hls流自动播放及全屏非全屏播放 首先使用了hls.js插件,可以实现在P ...