图的第k短路

【问题描述】

给你一个有向图,求从1到n的第k短路。

【解法】

SPFA+A*搜索。

1 A*算法

A*算法在人工智能中是一种典型的启发式搜索算法,启发中的估价是用估价函数表示的:

h(n)=f(n)+g(n)

其中f(n)是节点n的估价函数,g(n)表示实际状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。另外定义h‘(n)为n到目标节点最佳路径的实际值。如果h‘(n)≥h(n)则如果存在从初始状态走到目标状态的最小代价的解,那么用该估价函数搜索的算法就叫A*算法。

2 第K最短路的算法

我们设源点为s,终点为t,我们设状态f(i)的g(i)为从s走到节点i的实际距离,h(i)为从节点i到t的最短距离,从而满足A*算法的要求,当第K次走到f(n-1)时表示此时的g(n-1)为第K最短路长度。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<ctime>
  7 #include<algorithm>
  8 #include<queue>
  9 #define MAXN 20100
 10 #define INF 1000100000
 11 #define pii pair<int,int>
 12 using namespace std;
 13 struct node{int y,next,v;}e1[MAXN],e2[MAXN];
 14 struct node2
 15 {
 16     int f,g,id;
 17     friend bool operator < (node2 a,node2 b)
 18     {
 19         return a.f>b.f;
 20     }
 21 };
 22 int n,m,k,len1,len2,Link1[MAXN],Link2[MAXN],dis[MAXN],vis[MAXN],tim[MAXN],ans[MAXN];
 23 priority_queue<node2>Q;
 24 inline int read()
 25 {
 26     int x=0,f=1;  char ch=getchar();
 27     while(!isdigit(ch))  {if(ch==‘-‘)  f=-1;  ch=getchar();}
 28     while(isdigit(ch))  {x=x*10+ch-‘0‘;  ch=getchar();}
 29     return x*f;
 30 }
 31 void insert(int xx,int yy,int vv)
 32 {
 33     e1[++len1].next=Link1[xx];
 34     Link1[xx]=len1;
 35     e1[len1].y=yy;
 36     e1[len1].v=vv;
 37     e2[++len2].next=Link2[yy];
 38     Link2[yy]=len2;
 39     e2[len2].y=xx;
 40     e2[len2].v=vv;
 41 }
 42 void SPFA()
 43 {
 44     priority_queue<int,vector< int >,greater< int > >q;
 45     memset(dis,50,sizeof(dis));
 46     dis[1]=0,vis[1]=1,q.push(1);
 47     while(!q.empty())
 48     {
 49         int tn=q.top();
 50         vis[tn]=0;
 51         q.pop();
 52         for(int i=Link2[tn];i;i=e2[i].next)
 53         {
 54             int tmp=e2[i].y;
 55             if(dis[tmp]>dis[tn]+e2[i].v)
 56             {
 57                 dis[tmp]=dis[tn]+e2[i].v;
 58                 if(!vis[tmp])
 59                 {
 60                     vis[tmp]=1;
 61                     q.push(tmp);
 62                 }
 63             }
 64         }
 65     }
 66 }
 67 void Astar()
 68 {
 69     if(dis[n]==INF)  return;
 70     node2 temp;  temp.g=0,temp.f=dis[n],temp.id=n;
 71     Q.push(temp);
 72     while(!Q.empty())
 73     {
 74         temp=Q.top(); Q.pop();
 75         if(temp.id==1)  {ans[++ans[0]]=temp.f;  if(ans[0]>k)  return;}
 76         for(int i=Link1[temp.id];i;i=e1[i].next)
 77         {
 78             node2 opt;
 79             opt.g=temp.g+e1[i].v;
 80             opt.f=opt.g+dis[e1[i].y];
 81             opt.id=e1[i].y;
 82             Q.push(opt);
 83         }
 84     }
 85 }
 86 int main()
 87 {
 88     n=read();  m=read();  k=read();
 89     for(int i=1;i<=m;i++)
 90     {
 91         int x=read(),y=read(),v=read();
 92         insert(x,y,v);
 93     }
 94     SPFA();
 95     Astar();
 96     for(int i=1;i<=k;i++)
 97     {
 98         if(!ans[i])  printf("-1\n");
 99         else printf("%d\n",ans[i]);
100     }
101     return 0;
102 }

时间: 2024-11-05 06:29:25

图的第k短路的相关文章

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

POJ 2499 A*求第K短路

DES就是给你一个图.然后给你起点和终点.问你从起点到终点的第K短路. 第一次接触A*算法. // 大概懂思路了.A*算法需要的估价函数里的两个函数.一个是起点到当前点的消耗. //一个是当前点到目标点的估测消耗.所以需要用Dijstra或者Spfa求出目标点到所有点的最短路. //然后就可以用A*算法来求了. // 确实.学了位运算.链式表. #include<cstdio> #include<iostream> #include<queue> #include<

次短路 + 第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 魔法猪学院 A*k短路

题目大意:给定一个值E 求起点到终点的最多条路径 使长度之和不超过E k短路的A*算法--每一个点有一个估价函数=g[x]+h[x] 当中g[x]是从源点出发已经走了的长度 h[x]是从这个点到汇点的最短路 首先先在反图上跑一遍SPFA求出每一个点的h[x],然后将源点的g[x]+h[x]增加堆 每次取出堆顶时将堆顶的g[x]向所连接的边扩展 第k次取出汇点即是答案 当中有一个剪枝就是当第k+1次取出某个点时不继续拓展 防止MLE 可是这里k未知 我们能够对k进行估价处理 初始k=floor(E

poj 2449 Remmarguts&#39; Date(K短路,A*算法)

http://poj.org/problem?id=2449 大致题意:给出一个有向图,求从起点到终点的第K短路. K短路与A*算法详解  学长的博客... 算法过程 #include <stdio.h> #include <iostream> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #in

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 A*求k短路

A*的入门题目,需要注意的是当图中只有一个点的时候k短路是不存在的. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 7 const int INF = 0x3f3f3f3f; 8 const int N = 1001; 9 const int M = 100000; 10 int head[N

POJ2449 Remmarguts&#39; Date 【k短路】

Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 21064   Accepted: 5736 Description "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, h