最短路 次短路 k短路(k很小)

最短路

luogu 3371

https://www.luogu.org/problemnew/show/P3371

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn=1e4+10;
 8
 9 int dist[maxn];
10 bool vis[maxn];
11
12 struct node
13 {
14     int d,len;
15     ///相反
16     bool operator<(const node & b) const
17     {
18         return b.len<len;    ///b.d放在左边,方便
19     }
20 };
21
22 priority_queue<node> st;///这样写就可以了,省略后面的部分
23 vector<pair<int,int> >e[maxn];
24
25 int main()
26 {
27     int n,m,s,x,y,z,d,i;
28     vector<pair<int,int> >::iterator j;
29     scanf("%d%d%d",&n,&m,&s);
30     for (i=1;i<=m;i++)
31     {
32         scanf("%d%d%d",&x,&y,&z);
33         //有向边
34         e[x].push_back(make_pair(y,z));
35     }
36     memset(dist,0x7f,sizeof(dist));
37     dist[s]=0;
38     st.push({s,0});
39     ///点可以重复在priority_queue出现
40     while (1)
41     {
42         ///该点已被处理
43         ///若st为空,执行st.top()会报错
44         while (!st.empty() && vis[st.top().d])
45             st.pop();
46         ///必不可少
47         if (st.empty())
48             break;
49         ///以dist[d]为点d的最短路为基础,进行拓展
50         d=st.top().d;
51         vis[d]=1;///!
52         st.pop();///!
53         for (j=e[d].begin();j!=e[d].end();j++)
54             if (dist[j->first]>dist[d]+j->second)
55             {
56                 dist[j->first]=dist[d]+j->second;
57                 st.push({j->first,dist[j->first]});
58             }
59     }
60     for (i=1;i<=n;i++)
61     {
62         if (i!=1)
63             printf(" ");
64         printf("%d",dist[i]==dist[0]?2147483647:dist[i]);
65     }
66     return 0;
67 }

次短路

poj3255

http://poj.org/problem?id=3255

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn=5e3+10;
 8 int ci=2;
 9
10 ///次短路,可以推广位k短路(当然k要较小),此时dist的第二维的大小需要增加,第二维的数据修改也要修改
11
12 struct node
13 {
14     int d,len;
15     node *next;
16 }*e[maxn];
17
18 struct rec
19 {
20     int d,dist;
21     bool operator<(const rec &b) const
22     {
23         return b.dist<dist;
24     }
25 };
26 priority_queue<rec> st;
27
28 int hap[maxn],dist[maxn][3];
29
30 int main()
31 {
32     int i,a,b,c,n,m,d,dis,dd,ddis;
33     node *p;
34     scanf("%d%d",&n,&m);
35     for (i=1;i<=m;i++)
36     {
37         scanf("%d%d%d",&a,&b,&c);
38         p=new node();
39         p->d=b;
40         p->len=c;
41         p->next=e[a];
42         e[a]=p;
43
44         p=new node();
45         p->d=a;
46         p->len=c;
47         p->next=e[b];
48         e[b]=p;
49     }
50
51     ///from 1 to n
52     memset(dist,0x7f,sizeof(dist));
53     dist[1][1]=0;
54     st.push({1,0});
55     while (1)
56     {
57         while (!st.empty() && hap[st.top().d]==ci)
58             st.pop();
59         ///if not exists(not break in the next period)
60         if (st.empty())
61             break;
62
63         ///确定了d,dist是第hap[d]小,以此为基础拓展其它点的第一小和第二小
64         d=st.top().d;
65         dis=st.top().dist;
66         hap[d]++;
67         st.pop();
68
69         if (d==n && hap[d]==2)
70             break;
71
72         p=e[d];
73         while (p)
74         {
75             dd=p->d;
76             ddis=dis+p->len;
77             if (ddis<dist[dd][1])
78             {
79                 dist[dd][2]=dist[dd][1];
80                 dist[dd][1]=ddis;
81                 st.push({dd,ddis});///{d,dis[dd][1]}已经在优先队列里了
82             }
83             else if (ddis<dist[dd][2])
84             {
85                 dist[dd][2]=ddis;
86                 st.push({dd,ddis});
87             }
88             p=p->next;
89         }
90     }
91     ///if not exists
92     printf("%d",dist[n][2]);
93     return 0;
94 }

原文地址:https://www.cnblogs.com/cmyg/p/10063159.html

时间: 2024-11-05 19:27:12

最短路 次短路 k短路(k很小)的相关文章

【k短路&amp;A*算法】BZOJ1975: [Sdoi2010]魔法猪学院

Description 找出1~k短路的长度. Solution k短路的求解要用到A*算法 A*算法的启发式函数f(n)=g(n)+h(n) g(n)是状态空间中搜索到n所花的实际代价 h(n)是n到结束状态最佳路径的估计代价 关于h(n)的选取,当h(n)<实际代价时,搜索慢但可出解:h(n)=实际代价时,正确率与效率最高:h(n)>实际代价,快但只能得到近似解. 但在k短路问题中,h(n)是可以选到准确值的,就是n到结束节点的最短路,预处理时从结束节点做一次单源最短路即可. 按广搜的方式

再探第k短路

其实这是一个很古老的姿势啦- 只不过今天跟同学讨论A*算法求k短路的时候,同学不信A*算法能被卡掉. 于是我翻了翻课件找出了一种n元环的特殊情况,卡掉了A*算法. A*算法是只有到达终点的时候才能统计答案,这导致可能拓展很多个状态才能得到一个用来更新答案的有效状态. 例如一个n元环,当我们到达终点之后,可能还要拓展n次才能得到下一个状态.于是若求k短路时间复杂度就为O(nk).于是就容易被卡掉. 我们考虑换一种方式来定义一条从起点s到终点t的路径. 构建出以t为终点的最短路树,t是这棵树的根,对

次短路 + 第K短路 模版

虽然从字面上看,次短路和第2短路是一样的.但是我在题目中遇到的却不是这样的. 在有些题目中,需要判断次短路是否存在.比如说,u.v之间只有一条路径.那么只有最短路.次短路是不存在的.这时候,解题方法是先求出最短路,然后枚举删除最短路径中的边,然后求最小值.题目可以看poj3986. 第K短路的实现是 SPFA + A* 算法. A*算法通过一个估价函数f(h)来估计途中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时,它会尝试其他路径.对于A*,估价函数 = 当前值 + 当前位置

HDU 6181 次短路(K短路)

Two Paths Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)Total Submission(s): 613    Accepted Submission(s): 312 Problem Description You are given a undirected graph with n nodes (numbered from 1 to n) and m edge

Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1357  Solved: 446[Submit][Status][Discuss] Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig 今

bzoj 1598: [Usaco2008 Mar]牛跑步 -- 第k短路,A*

1598: [Usaco2008 Mar]牛跑步 Time Limit: 10 Sec  Memory Limit: 162 MB Description BESSIE准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚. BESSIE也不想跑得太远,所以她想走最短的路经. 农场上一共有M (1 <= M <= 10,000)条路, 每条路连接两个用1..N(1 <= N <= 1000)标号的地点. 更方便的是,如果X>Y,则地点X

POJ 2449 Remmarguts&#39; Date (A*搜索求K短路)

传送门 这是一道裸的K短路的问题,我们将会用A*解决. 我们设计估值函数h的时候可以像这样想.因为h(n) <= h*(n)而且要尽量接近h*(n),所以我们想到,可以求一个从目标节点到其余节点的最短路,这个一定是小于等于实际值的.然后就用A*从起点开始搜索,找到一个节点v,就使cnt[v]加1.当cnt[v] > k时就可以剪枝了,因为这一定不再K短路的路线上了.很好通过反证法得到证明.当目标节点被搜索到了第k次的时候就可以结束搜索了. 要注意这道题有一个很坑的地方,就是若给出的起点=终点,

POJ2449 Remmarguts&#39; Date 第K短路

POJ2449 比较裸的K短路问题 K短路听起来高大上 实际思路并不复杂 首先对终点t到其他所有点求最短路 即为dist[] 然后由起点s 根据当前走过的距离+dist[]进行A*搜索 第k次到达t即为第K短路 代码也很简单 //数组开的不够 不一定是运行时错误! 可能也会WA #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath&g

BZOJ 1975 SDOI 2010 魔法猪学院 A*求K短路

题目大意:给出一张无向图,给出一个数值m,求出从1到N的前k短路的长度和>=数值m. 思路:注意!不能使用priority_queue,否则你会死的很惨..为了解惑,我去找了当年SD省选的原题,分明空间是256M,为什么BZOJ和BASHUOJ上都是64M??卡pq有意思么??? 思路很简单,就是按顺序求出这张图的前k短路,然后当m减成负数的时候就返回. CODE: #include <queue> #include <cstdio> #include <cstring