• Acwing 178 第k短路 (dijkstra+A*)


    题面

    给定一张N个点(编号1,2…N),M条边的有向图,求从起点S到终点T的第K短路的长度,路径允许重复经过点或边。

    注意: 每条最短路中至少要包含一条边。

    输入格式
    第一行包含两个整数N和M。

    接下来M行,每行包含三个整数A,B和L,表示点A与点B之间存在有向边,且边长为L。

    最后一行包含三个整数S,T和K,分别表示起点S,终点T和第K短路。

    输出格式
    输出占一行,包含一个整数,表示第K短路的长度,如果第K短路不存在,则输出“-1”。

    数据范围
    1≤S,T≤N≤1000,
    0≤M≤105,
    1≤K≤1000,
    1≤L≤100
    输入样例:
    2 2
    1 2 5
    2 1 4
    1 2 2
    输出样例:
    14

    思路

    k短路的板子题,我们先从终点开始跑一边最短路作为我们a里面要用的估价函数。然后去跑A,当我们第k次到达终点,那么这个距离就是我们要求的第k短路。

    代码实现

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int maxn=200010;
    const int N=1010;
    typedef pair<int,int > PII;
    typedef pair<int,PII> PIII;
    
    int m,n,s,t,k;
    int cnt,tot,head1[maxn],head2[maxn];
    int f[N],dis[N],vis[N];
    struct edge {
        int w,v,nex;
        edge (int w=0,int v=0,int nex=0) :w(w), v(v), nex(nex) {}
    }e1[maxn],e2[maxn];
    
    inline void add1 (int u,int v,int w) {
       e1[++cnt]=edge (w,v,head1[u]);
       head1[u]=cnt;
    }
    
    inline void add2 (int u,int v,int w) {
       e2[++tot]=edge (w,v,head2[u]);
       head2[u]=tot;
    }
    
    
    inline void init () {
        memset (vis,0,sizeof (vis));
        memset (dis,0x3f3f3f3f,sizeof (dis));
        memset (head1,-1,sizeof (head1));
        memset (head2,-1,sizeof (head2));
    }
    
    inline void dijkstra () {
       priority_queue <PII,vector<PII>,greater <PII> > q;
       dis[t]=0;
       q.push (PII{0,t});
    
       while (q.size ()) {
           PII u=q.top ();
           q.pop ();
    
           if (vis[u.second]) continue;
           vis[u.second]=1;
           for (int i=head1[u.second];i!=-1;i=e1[i].nex) {
               int v=e1[i].v;
               if (dis[v]>dis[u.second]+e1[i].w) {
                   dis[v]=dis[u.second]+e1[i].w;
                   q.push (PII{dis[v],v});
               }
           }
       }
       memcpy (f,dis,sizeof (dis));
    }
    
    inline int a_star () {
        priority_queue<PIII,vector<PIII>,greater <PIII> > q;
        
        q.push (PIII{f[s],{0,s}});
        memset (vis,0,sizeof (vis));
    
        while (q.size ()) {
            PIII u=q.top ();
            q.pop ();
    
            int ver=u.second.second,distance=u.second.first;
            if (vis[ver]>=k) continue;
            vis[ver]++;
            if (ver==t&&vis[ver]==k) return distance;
            for (int i=head2[ver];i!=-1;i=e2[i].nex) {
                int v=e2[i].v;
                if (vis[v]<k) {
                    q.push ({distance+e2[i].w+f[v],{distance+e2[i].w,v}});
                }
            }
        }
        return -1;
    }
    
    int main () {
        cin>>n>>m;
        init ();
        for (int i=1;i<=m;i++) {
            int x,y,z;
            cin>>x>>y>>z;
            add2 (x,y,z);
            add1 (y,x,z);
        }   
        cin>>s>>t>>k;
        if (t==s) k++;
        dijkstra ();
    
        cout<<a_star()<<endl;
    
        return 0;
    }
    
  • 相关阅读:
    Android 剪贴板详解
    Android 7.1
    Windows 上安装 Redis 及可能出现的错误和解决方法!
    微信支付(服务商模式问题集)
    LOG4J日志问题 Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    Mysql强制修改密码
    Mysql密码忘记,修改密码方法
    笔记本最大支持内存查看方法
    Liunx操作指令搜素引擎
    tomcat启动时,内存溢出,Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
  • 原文地址:https://www.cnblogs.com/hhlya/p/13361311.html
Copyright © 2020-2023  润新知