• 【POJ2449】第k短路


    最短路是一个妇孺皆知的算法,可以用多种方法解决。但是第k短路……

    以Dijkstra为例,对于s->t的第k短路,即t点在堆中第k次取出的结果。

    于是我们想到了一个朴素的算法:用Dijkstra反复执行,直到t点在堆中第k次取出时结束。

    考虑一下优化:用A*算法优化。

    根据A*估价函数的设计原则,x->T的估计距离应当不大于x->T的实际距离,显然,我们采用x->T的最短路作为估价,这样既符合题意,又方便求解,这相当于在反向边上求解单源最短路径,在此不在赘述。

    此时,我们用朴素算法求解,不同之处在于现在的Dijkstra堆中保存从起点到当前节点已经花费的代价+从当前节点到终点的最短路径(估价函数),这样再按照朴素算法求解。

    A*优化后的时间复杂度最坏时与朴素算法相同(相当于估价函数的值为0),但是由于估价函数的作用,很多节点的访问次数远远小于k,因此A*优化后的算法能够较快解决问题。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <queue>
     5 #include <algorithm>
     6 typedef long long ll;
     7 inline int read() {
     8     int ret=0,f=1;
     9     char c=getchar();
    10     while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    11     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
    12     return ret*f;
    13 }
    14 using namespace std;
    15 struct edge {
    16     int next,to,dis;
    17 }a[100010<<1],a1[100010<<1];
    18 int head[100010],head1[100010],num,num1;
    19 int dis[1010],vis[1010],sum[1010];
    20 struct node {
    21     int id,dis,val;
    22     bool operator <(const node &x) const {
    23         return dis+val>x.dis+x.val;
    24     }
    25 };
    26 priority_queue<node> q;
    27 priority_queue< pair<int,int> >qq;
    28 int n,m,k,s,t;
    29 inline void add(int from,int to,int dis) {
    30     a[++num].next=head[from];
    31     a[num].to=to;
    32     a[num].dis=dis;
    33     head[from]=num;
    34 }
    35 inline void add1(int from,int to,int dis) {
    36     a1[++num1].next=head1[from];
    37     a1[num1].to=to;
    38     a1[num1].dis=dis;
    39     head1[from]=num1;
    40 }
    41 int main() {
    42     n=read(); m=read();
    43     for(int i=1,x,y,z;i<=m;i++) {
    44         x=read(); y=read(); z=read();
    45         add(x,y,z);
    46         add1(y,x,z);
    47     }
    48     s=read(); t=read(); k=read();
    49     if(s==t) k++;
    50     memset(dis,0x3f,sizeof(dis));
    51     dis[t]=0;
    52     qq.push(make_pair(0,t));
    53     while(!qq.empty()) {
    54         int now=qq.top().second;
    55         qq.pop();
    56         if(vis[now]) continue ;
    57         vis[now]=1;
    58         for(int i=head1[now];i;i=a1[i].next)
    59             if(dis[a1[i].to]>dis[now]+a1[i].dis) {
    60                 dis[a1[i].to]=dis[now]+a1[i].dis;
    61                 qq.push(make_pair(-dis[a1[i].to],a1[i].to));
    62             }
    63     }
    64     node noww;
    65     noww.id=s;
    66     noww.val=0;
    67     noww.dis=dis[s];
    68     q.push(noww);
    69     while(!q.empty()) {
    70         node now=q.top();
    71         q.pop();
    72         sum[now.id]++;
    73         if(sum[now.id]>k) continue ;
    74         if(now.id==t&&sum[now.id]==k) {
    75             printf("%d
    ",now.val);
    76             return 0;
    77         }
    78         for(int i=head[now.id];i;i=a[i].next) {
    79             node neww;
    80             neww.id=a[i].to; neww.dis=dis[a[i].to];
    81             neww.val=now.val+a[i].dis;
    82             q.push(neww);
    83         }
    84     }
    85     puts("-1");
    86     return 0;
    87 }
    AC Code
  • 相关阅读:
    postgresql批量删除表
    Oracle迁移至PostgreSQL工具之Ora2Pg
    postgresql获取表最后更新时间(通过发布订阅机制将消息发送给应用程序)
    postgresql获取表最后更新时间(通过表磁盘存储文件时间)
    postgresql获取表最后更新时间(通过触发器将时间写入另外一张表)
    postgresql源码编译安装(centos)
    Java 学习笔记(7)——接口与多态
    Java 学习笔记(6)——继承
    Java 学习笔记(4)——java 常见类
    Java 学习笔记(4)——面向对象
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10627799.html
Copyright © 2020-2023  润新知