poj 2449
来源:互联网 发布:2016网络作家富豪榜 女 编辑:程序博客网 时间:2024/06/05 09:19
题目概述
有N个地点,编号1到N,地点之间有M条单向路,要沿着第K短路从S到T,问其用时
时限
4000ms/12000ms
输入
第一行整数N,其后N行,每行三个整数a,b,c,描述一条路的起点,终点,途经用时,最后一行三个整数S,T,K,输入只有一组
限制
1<=N<=1000;1<=M<=100000;1<=c<=100;1<=K<=1000
输出
一个数,所求用时,若不存在第K短路则为-1
样例输入
2 2
1 2 5
2 1 4
1 2 2
样例输出
14
讨论
图论,第K短路,bellman_ford队列优化+A*,先将图中边反转,构图求最短路,这是从T到其他点的最短距离,然后A*,A*需要利用一个公式,f=g+h,这里h就是刚求的T到其他某点最短路长,g是从S到同一个点最短路长,f的意义自然就是从S经过某点到T的最短路长,显然经过的这个某个点不一定是最短路上的点,因而这条路也不一定最短路,但一定是经过这个点的最短路,那这就好办了,把所有的f都排序,去掉最短的,下一个就是次短,再去,就是第三短,最终总能找到第K短的,由于不知道到底哪些点在最短路上,因而选定这个某个点为终点T就好了,终点肯定在最短路上,第K次遇到这个某个点为终点的路,这条路就是第K短路,为什么不选起点?因为f描述的就是从起点S出发的,起点和终点都是自己,这不符合条件
从实现层面上,首先需要一个优先队列完成上述排序工作,每次弹出一个点,然后将其连接的点计算出f,之后塞到队列中,另外需要注意优先队列每次弹出的是最大的,因而重载小于号时需要留意,重载方向错也能过样例,但只会是MLE,因为会无限入队,另外有个坑,起点就是终点的时候不能算,可惜额没有找到原题中这句话在哪里
题目的意思到底是什么已经不重要了,可能是双向路,也可能是从T到S,但是都一样能做
实际上题解并不是最快的一次,但写的比较规整一点
题解状态
7476K,266MS,C++,1599B
题解代码
#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define INF 0x3f3f3f3f#define MAXN 1003#define memset0(a) memset(a,0,sizeof(a))int N, M, S, T, K, index, dis[MAXN];//地点数 路数 起点编号 终点编号 第K短路 index 为邻接表提供下标 distance 也就是公式中的hint to1[MAXN * 100], w1[MAXN * 100], pre1[MAXN * 100], al1[MAXN];//正方向图int to2[MAXN * 100], w2[MAXN * 100], pre2[MAXN * 100], al2[MAXN];//反方向图struct It//A*中用到的路的结构{ int to, g;//路的终点 从S到to的最短路长 bool operator<(const It &b)const { return g + dis[to] > b.g + dis[b.to];//之前由于这个写反了贡献一排MLE }};priority_queue<It>pq;//A*的优先队queue<int>q;//bellman_ford的队bool inq[MAXN];//bellman_ford的辅助数组 在队中int fun(){ index = 1; for (int p = 0; p < M; p++) { int a, b, c; scanf("%d%d%d", &a, &b, &c);//input to1[index] = b, w1[index] = c, pre1[index] = al1[a], al1[a] = index; to2[index] = a, w2[index] = c, pre2[index] = al2[b], al2[b] = index++;//这是两张图 因而下标一样也无所谓 } scanf("%d%d%d", &S, &T, &K);//input for (int p = 1; p <= N; p++)//下面是bellman_ford算法 dis[p] = INF; dis[T] = 0; q.push(T); while (!q.empty()) { int a = q.front(); q.pop(); inq[a] = 0; for (int p = al2[a]; p; p = pre2[p]) { if (dis[to2[p]] > dis[a] + w2[p]) { dis[to2[p]] = dis[a] + w2[p]; if (!inq[to2[p]]) { q.push(to2[p]); inq[to2[p]] = 1; } } } } It a, b;//下面是A*算法 int cnt = 0; if (S == T)//起点就是终点时要额外数一条路 K++; if (dis[S] == INF)//如果bellman_ford已经认定没有路就不用继续了 return -1; a.to = S, a.g = 0; pq.push(a); while (!pq.empty()) { a = pq.top(); pq.pop(); if (a.to == T) cnt++; if (cnt == K) return a.g; for (int p = al1[a.to]; p; p = pre1[p]) { b.to = to1[p], b.g = a.g + w1[p]; pq.push(b); } } return -1;//这行似乎是多余的 但是没有试过}int main(void){ //freopen("vs_cin.txt", "r", stdin); //freopen("vs_cout.txt", "w", stdout); scanf("%d%d", &N, &M);//input printf("%d\n", fun());//output}
EOF
- poj 2449
- POJ 2449
- poj 2449
- poj 2449
- POJ 2449
- POJ 2449 A*+SPFA
- poj 2449 Remmarguts' Date
- 【k短路】POJ 2449
- POJ 2449 A*+spfa
- POJ 2449 Remmarguts' Date
- POJ 2449 K-短路
- poj 2449 k短路
- POJ 2449 Remmarguts' Date
- poj 2449 Remmarguts' Date
- POJ 2449: Remmarguts' Date
- poj 2449 k短路
- POJ 2449 Remmarguts' Date
- K短路-POJ-2449
- eclipse查看类源码出现failed to create the part's controls的解决方法
- Java中native关键字
- string 和 char *两者的区别是什么 ?
- C语言字符串处理及内存管理函数
- HDU5831(水题,有一点容易忽略,导致一直WAWAWA)
- poj 2449
- Leetcode 274. H-Index (Medium) (cpp)
- Java的native关键字
- POJ 2155 Matrix
- 嵌入式开发第26天(信号、system V IPC、内存映射)
- 【NOIP提高】奇袭
- 利用getLayoutParams()方法和setLayoutParams()方法
- 数据结构实验之二叉树一:树的同构
- java中static关键字