zoukankan      html  css  js  c++  java
  • 算法长度K最短路问题(单源点最短路径+A*算法)Strut2教程java教程

    最近研究算法长度,稍微总结一下,以后继续补充:

        每日一道理
    “多难兴才”曾一度被人定为规律。请看:屈原被放逐而作《离骚》;司马迁受宫刑而作《史记》;欧阳修两岁丧父笃学而成才;曹雪芹举家食粥而写出了不朽的《红楼梦》;越王勾践卧薪尝胆而雪洗国耻;韩信遭胯下辱而统率百万雄兵……他们都是在与逆境搏斗中成为伟人的!
    /*
     *算法引入:
     *在单源点最短径路题问中,现实运用时还需晓得最短径路外,次短路或者第三短路;
     *即要晓得多条最短路,并出排其长度加增的序顺,即为K最短路题问;
     *
     *算法想思:
     *单源点最短径路+高等搜索A*;
     *A*算法结合了启发式方法和式形化方法;
     *启发式方法通过充分利用图给出的信息来动态地做出定决而使搜索数次大大下降;
     *式形化方法不利用图给出的信息,而仅通过数学的式形析分;
     *
     *算法通过一个估价数函f(h)来估计图中的以后点p到点终的距离,并由此定决它的搜索向方;
     *当这条径路失败时,它会实验其他径路;
     *对于A*,估价数函=以后值+以后置位到点终的距离,即f(p)=g(p)+h(p),每次扩展估价数函值最小的一个;
     *
     *对于K短路算法说来,g(p)为以后从s到p所走的径路的长度;h(p)为点p到t的最短路的长度;
     *f(p)的意思为从s按照以后径路走到p后再走到点终t一共少至要走多远;
     *
     *为了减速算计,h(p)需要在A*搜索之前停止预处理,只要将原图的有所边反向,再从点终t做一次单源点最短径路能就失掉每一个点的h(p)了;
     *
     *算法骤步:
     *(1),将有向图的有所边反向,以原点终t为源点,求解t到有所点的最短距离;
     *(2),新建一个优先列队,将源点s加入到列队中;
     *(3),从优先级列队中弹出f(p)最小的点p,如果点p就是t,则算计t出队的数次;
     *如果以后为t的第k次出队,则以后径路的长度就是s到t的第k短路的长度,算法结束;
     *否则遍历与p相连的有所的边,将扩展出的到p的邻接点信息加入到优先级列队;
     *
     *算法测试:
     *PKU2449(Remmarguts' Date)
     *
     *标题粗心:
     *求从s到t的第k短路的长度;
     */
    
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<cstdio>
    #include<climits>
    #include<algorithm>
    using namespace std;
    
    const int INF=0xffffff;
    const int N=1010;
    const int M=100010;
    
    struct node1
    {
        int to;
        int w;
        int next;
    };
    
    node1 edge1[M],edge2[M];
    int head1[M],head2[M];
    int idx1,idx2;
    int dist[N];
    
    struct node2
    {
        int to;
        //g(p)为以后从s到p所走的径路的长度;h(p)为点p到t的最短路的长度;
        int g,f;//f=g+h,f(p)的意思为从s按照以后径路走到p后再走到点终t一共少至要走多远;
        bool operator<(const node2 &r ) const
        {
            if(r.f==f)
                return r.g<g;
            return r.f<f;
        }
    };
    
    void Addedge1(int u,int v,int w)
    {
        edge1[idx1].w=w;
        edge1[idx1].to=v;
        edge1[idx1].next=head1[u];
        head1[u]=idx1++;
    }
    
    void Addedge2(int u,int v,int w)
    {
        edge2[idx2].w=w;
        edge2[idx2].to=v;
        edge2[idx2].next=head2[u];
        head2[u]=idx2++;
    }
    
    bool SPFA(int s,int n,int head[],node1 edge[],int dist[])
    {
        queue<int>Q1;
        int inq[N];
        for(int i=0; i<=n; i++)
        {
            dist[i]=INF;
            inq[i]=0;
        }
        dist[s]=0;
        Q1.push(s);
        inq[s]++;
        while(!Q1.empty())
        {
            int q=Q1.front();
            Q1.pop();
            inq[q]--;
            if(inq[q]>n)//负权环
                return false;
            int k=head[q];
            while(k>=0)
            {
                if(dist[edge[k].to]>dist[q]+edge[k].w)
                {
                    dist[edge[k].to]=edge[k].w+dist[q];
                    if(!inq[edge[k].to])
                    {
                        inq[edge[k].to]++;
                        Q1.push(edge[k].to);
                    }
                }
                k=edge[k].next;
            }
        }
        return true;
    }
    
    int A_star(int s,int t,int n,int k,int head[],node1 edge[],int dist[])
    {
        node2 e,ne;
        int cnt=0;
        priority_queue<node2>Q;
        if(s==t)//当s==t时,距离为0的路不能算在这k短路中,所以需要求k+1短路;
            k++;
        if(dist[s]==INF)
            return -1;
        e.to=s;
        e.g=0;
        e.f=e.g+dist[e.to];
        Q.push(e);
    
        while(!Q.empty())
        {
            e=Q.top();
            Q.pop();
            if(e.to==t)//找到一条最短径路
            {
                cnt++;
            }
            if(cnt==k)//找到k短路
            {
                return e.g;
            }
            for(int i=head[e.to]; i!=-1; i=edge[i].next)
            {
                ne.to=edge[i].to;
                ne.g=e.g+edge[i].w;
                ne.f=ne.g+dist[ne.to];
                Q.push(ne);
            }
        }
        return -1;
    }
    
    int main()
    {
        int n,m;
        //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
        while(~scanf("%d%d",&n,&m))
        {
            memset(head1, -1, sizeof(head1));
            memset(head2, -1, sizeof(head2));
            idx1=idx2=0;
            int u,v,w;
            for(int i=0; i<m; i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                Addedge1(u,v,w);
                Addedge2(v,u,w);
            }
            int s,t,k;
            scanf("%d%d%d",&s,&t,&k);
            SPFA(t,n,head2,edge2,dist);//以原点终t为源点,求反向图中t到有所点的最短距离;
            int res=A_star(s,t,n,k,head1,edge1,dist);
            printf("%d\n",res);
        }
        return 0;
    }

    文章结束给大家分享下程序员的一些笑话语录: 不会,Intel会维持高利润,也会维持竞争局面,国外的竞争不是打死对方的那种。你看日本有尼康,佳能,索尼,都做相机,大家都过得很滋润。别看一堆厂,其实真正控制的是后面的那几个财团——有些竞争对手,后面其实是一家人。

  • 相关阅读:
    VS的ncb、pdb文件分析
    理解First Chance和Second Chance避免单步调试
    Visual Studio调试之符号文件
    Visual Studio调试之断点技巧篇补遗
    Visual Studio调试之断点技巧篇
    不能设置断点的检查步骤
    调试术语
    Visual Studio调试之断点基础篇
    Visual Studio调试之断点进阶篇
    复制
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3053767.html
Copyright © 2011-2022 走看看