K短路,顾名思义,是让你求从$s$到$t$的第$k$短的路。

暴力当然不可取,那么我们有什么算法可以解决这个问题?

--------------------------

首先,我们要维护一个堆。

struct node
{
int dist,pos;
bool operator <(const node&x) const
{
return dist>x.dist;
}
}
priority_queue<node> q;

这个堆是用来干什么的?

----------------------------------------------

这时候要提到一种新算法:A*算法。

估价函数:$f[i]=g[i]+h[i]$。其中,$g[i]$是从起点$s$走,按照这条路径到当前点已经走了多少路程,$h[i]$是当前点到终点$t$的最短路。

我们用之前开设的堆来维护这个估价函数,这样到达第k次终点$t$的路径即为所求。

Code(这里是[SDOI2010]魔法猪学院的A*算法):

void Astar(int kk)
{
priority_queue<SKT> q;
memset(vis,,sizeof(vis));
x.pos=;x.dist=0.0;x.h=0.0;
q.push(x);
while(!q.empty())
{
int now=q.top().pos;double d=q.top().dist;double hh=q.top().h;q.pop();
if (d>E) return;
vis[now]++;
if (now==n){ans++;E-=d;continue;}
if (vis[now]>kk) continue;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
SKT Faker;
Faker.pos=to;Faker.h=hh+edge[i].dis;Faker.dist=Faker.h+dis[to];
q.push(Faker);
}
}
}

----------------------------------

每个点到终点$t$的最短路怎么求?很简单,我们只要在建图的时候再建一个反向图,从终点跑单源最短路径即可。

Code:

void spfa()
{
for (int i=;i<=n;i++) dis[i]=0x3f3f3f3f;
queue<int> q;
q.push(n);dis[n]=0.0;vis[n]=;
while(!q.empty())
{
int now=q.front();q.pop();vis[now]=;
for (int i=Head[now];i;i=Edge[i].next)
{
int to=Edge[i].to;
if (dis[to]>dis[now]+Edge[i].dis)
{
dis[to]=dis[now]+Edge[i].dis;
if (!vis[to]) q.push(to),vis[to]=;
}
}
}
}

----------------------------

例题:[USACO08MAR]Cow Jogging G

近乎于K短路的裸题,只需要注意$u$大于$v$即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=;
const int maxm=;
int dis[maxn],vis[maxn];
int n,m,k;
struct SKT {
int v;
int dist;
bool operator < (const SKT&p) const {
return dist+dis[v]>p.dist+dis[p.v];
}
};
SKT x;
struct Node
{
int next,to,dis;
}edge[maxm],cont[maxm];
int heade[maxm],headc[maxm],cnt;
inline void add(int from,int to,int dis)
{
edge[++cnt].next=heade[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
heade[from]=cnt;
cont[cnt].next=headc[to];
cont[cnt].to=from;
cont[cnt].dis=dis;
headc[to]=cnt;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
void spfa()
{
queue<int> q;
for (int i=;i<=n;i++) dis[i]=0x7fffffff;
q.push();dis[]=;vis[]=;
while(!q.empty())
{
int now=q.front();q.pop();vis[now]=;
for (int i=headc[now];i;i=cont[i].next)
{
int to=cont[i].to;
if (dis[to]>dis[now]+cont[i].dis)
{
dis[to]=dis[now]+cont[i].dis;
if (!vis[to]) q.push(to),vis[to]=;
}
}
}
}
void Astar()
{
int ans=;
priority_queue<SKT> q;
x.v=n;x.dist=;
q.push(x);
while(!q.empty())
{
SKT now=q.top();q.pop();
if (now.v==) printf("%d\n",now.dist),++ans;
if (ans==k) return;
for (int i=heade[now.v];i;i=edge[i].next)
{
int to=edge[i].to;
if (to<now.v)
{
SKT Faker=now;
Faker.v=to;Faker.dist=now.dist+edge[i].dis;
q.push(Faker);
}
}
}
while(ans<k) cout<<-<<endl,++ans;
return;
}
signed main()
{
n=read(),m=read(),k=read();
for (int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
if (x>y) add(x,y,z);
}
spfa();
Astar();
return ;
}

最新文章

  1. 【BZOJ-1976】能量魔方Cube 最小割 + 黑白染色
  2. 替换所有字符串,获取url参数值
  3. SplendidCRM 中文语言包改正版
  4. Ubuntu 安装 ImageMagic(6.9.1-6)及 PHP 的 imagick (3.0.1)扩展
  5. jQuery 插件模板
  6. Win7下qt5.3.1+opencv2.4.9编译环境的搭建(好多 Opencv2.4.9源码分析的博客)
  7. IT第二十一天 - Collections、ArrayList集合、LinkedList集合、Set集合、HashMap集合、集合的操作注意【修20130828】
  8. Hashmat the brave warrior - UVa10055
  9. Android studio自动删除没用的资源
  10. Java中的i++和i--
  11. 用IDEA生成javadoc文档
  12. 冲刺NO.6
  13. tensorflow调试tfdbg
  14. 什么是 IP 隧道,Linux 怎么实现隧道通信?
  15. stm32f407以太网及USB OTG快速开发
  16. Android几种视频播放方式,VideoView、SurfaceView+MediaPlayer、TextureView+MediaPlayer,以及主流视频播放器开源项目
  17. java学习之路--StringBuffer常见的功能和实例
  18. leetcode 112. Path Sum 、 113. Path Sum II 、437. Path Sum III
  19. 关于RBAC的文章
  20. django 项目运行时media静态文件不能加载问题处理

热门文章

  1. 基于tcp/udp协议的套接字通信
  2. redux中的reducer为什么必须(最好)是纯函数
  3. 安装archlinux
  4. python面试题五:Python 编程
  5. SQLAlchemy01 /SQLAlchemy去连接数据库、ORM介绍、将ORM模型映射到数据库中
  6. 基于ConcurrentHashMap的本地缓存
  7. Oracle Database Tools
  8. Ethical Hacking - POST EXPLOITATION(1)
  9. webpack源码-依赖收集
  10. OGG19.1 oracle12c到oracle12c经典模式配置实施