zoukankan      html  css  js  c++  java
  • POJ 2449 Remmarguts' Date --K短路

    题意就是要求第K短的路的长度(S->T)。

    对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度。

    但是这种方法效率太低,会扩展出很多状态,所以考虑用启发式搜索A*算法。

    估价函数 = 当前值 + 当前位置到终点的距离,即F(p) = G(p) + H(p)。 

    G(p): 当前从S到p所走的路径距离

    H(p): 当前点p到终点T的最短路径距离   ---可以先将整个图边方向取反然后以T为源点求个最短路,用SPFA提速

    F(p): 从S按照当前路径走到p然后走到T一共至少走多远

    所以我们结合SPFA+A*可以解决。

    注意:当S==T时,需要计算第K+1短路,因为从S->T这条长度为0的路径不能算在内。

    还有,SPFA处判了一下负环。SPFA算法中,如果某个点出队次数大于n,说明此处存在负环。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <functional>
    #define Mod 1000000007
    using namespace std;
    #define N 1007
    
    struct node
    {
        int v;
        int g,f; //f = g+h
        bool operator < (const node &a)const
        {
            if(a.f == f)
                return a.g < g;
            return a.f < f;
        }
    };
    
    struct Edge
    {
        int v,w,next;
    }G[100*N],G2[100*N];
    
    int head[100*N],head2[100*N];
    int vis[N],dis[N];
    int out[N];
    int n,m,K,S,T,tot,tot2;
    
    void addedge(Edge *G,int& tot,int *head,int u,int v,int w)
    {
        G[tot].v = v;
        G[tot].w = w;
        G[tot].next = head[u];
        head[u] = tot++;
    }
    
    int SPFA(int s,int head[N],Edge G[N],int dis[N])
    {
        int i;
        queue<int> que;
        for(i=0;i<=n;i++)
            dis[i] = Mod;
        memset(vis,0,sizeof(vis));
        memset(out,0,sizeof(out));
        que.push(s);
        vis[s] = 1;
        dis[s] = 0;
        while(!que.empty())
        {
            int now = que.front();
            que.pop();
            vis[now] = 0;
            out[now]++;
            if(out[now] > n)
                return 0;
            for(int k=head[now];k!=-1;k=G[k].next)
            {
                if(dis[G[k].v] > dis[now] + G[k].w)
                {
                    dis[G[k].v] = dis[now] + G[k].w;
                    if(!vis[G[k].v])
                    {
                        vis[G[k].v] = 1;
                        que.push(G[k].v);
                    }
                }
            }
        }
        return 1;
    }
    
    int A_Star(int head[N],Edge G[N],int dis[N])
    {
        node tmp,now;
        int cnt = 0;
        priority_queue<node> que;
        if(S == T)
            K++;
        if(dis[S] == Mod)
            return -1;
        tmp.v = S;
        tmp.g = 0;
        tmp.f = tmp.g+dis[S];
        que.push(tmp);
        while(!que.empty())
        {
            tmp = que.top();
            que.pop();
            if(tmp.v == T)
                cnt++;
            if(cnt == K)
                return tmp.g;
            for(int i=head[tmp.v];i!=-1;i=G[i].next)
            {
                now.v = G[i].v;
                now.g = tmp.g + G[i].w;
                now.f = now.g + dis[now.v];
                que.push(now);
            }
        }
        return -1;
    }
    
    int main()
    {
        int i,j,u,v,w;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(head,-1,sizeof(head));
            memset(head2,-1,sizeof(head2));
            tot = tot2 = 1;
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                addedge(G,tot,head,u,v,w);   //原图
                addedge(G2,tot2,head2,v,u,w);   //反图
            }
            scanf("%d%d%d",&S,&T,&K);
            if(SPFA(T,head2,G2,dis))
            {
                int k_len = A_Star(head,G,dis);
                printf("%d
    ",k_len);
            }
            else
                puts("-1");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Spring Boot WebFlux-02——WebFlux Web CRUD 实践
    Struts2
    spring04
    spring03
    spring02
    jQuery04
    spring01
    jQuery03
    Linux学习笔记《六》
    请求报错:“应以Content-Type: application/x-www-form-urlencoded为请求类型,在form表单中提交登录信息。"
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3781028.html
Copyright © 2011-2022 走看看