POJ_2449_K最短路问题(单源最短路径+A*算法)

来源:互联网 发布:纳溪区网络问政平台 编辑:程序博客网 时间:2024/06/05 17:26

本文算法分析部分转载自:http://blog.csdn.net/jarily/article/details/8871968

/*  *算法引入:  *在单源点最短路径问题中,实际运用时还需知道最短路径外,次短路或者第三短路;  *即要知道多条最短路,并排出其长度增加的顺序,即为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短路的长度;  */  

刚开始写这道题的时候由于优先级自己写错了所以一直MLE,而后又yy说是不是vector的问题,就用数组去写,悲剧的是还是MLE;可是不能放弃,接着又自己傻乎乎地yy是不是最短路有问题,然后……然后就……傻傻地写了几个求解最短路的函数,可是发现还是没用啊!后来回头想想确实是优先级写错了,Orz……

题目链接:http://poj.org/problem?id=2449

vector 代码:

/* 代码中两个A*算法思路都是正确的 */#include<map>#include<queue>#include<stack>#include<cmath>#include<cctype>#include<ctime>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 1000 + 5;const int max_dis = 99999999;struct Edge{    int to;    int dis;    Edge(int to,int dis){        this -> to = to;        this -> dis = dis;    }};struct Node{    int st;    int g,h;    friend bool operator<(Node x,Node y){        return x.g+x.h>y.g+y.h;    }};int N,M;int A,B,T;int s,t,k;int Dis[maxn];int vis[maxn];vector<Edge>G1[maxn];vector<Edge>G2[maxn];typedef pair<int,int>P;/*void dij(int s){    fill(Dis+1,Dis+1+N,max_dis);    memset(vis,0,sizeof(vis));    Dis[s]=0;    while(true){        int v=-1;        for(int i=1;i<=N;i++){            if(!vis[i]&&(v==-1||Dis[i]<Dis[v]))                v=i;        }        if(v==-1) break;        vis[v]=1;        for(int i=0;i<G2[v].size();i++){            Edge& e=G2[v][i];            if(Dis[e.to]>Dis[v]+e.to)                Dis[e.to]=Dis[v]+e.to;        }    }}void dijkstra(int s){    fill(Dis+1,Dis+1+N,max_dis);    priority_queue<P,vector<P>,greater<P> >q;    while(q.size()) q.pop();    Dis[s]=0;    q.push(P(0,s));    while(q.size()){        P p=q.top(); q.pop();        int v=p.second;        if(p.first>Dis[v]) continue;        for(int i=0;i<G2[v].size();i++){            Edge& e=G2[v][i];            if(Dis[e.to]>Dis[v]+e.to){                Dis[e.to]=Dis[v]+e.to;                q.push(P(Dis[e.to],e.to));            }        }    }}*/void spfa(int s){    fill(Dis+1,Dis+N+1,max_dis);    memset(vis,0,sizeof(vis));    queue<int>q;    while(q.size()) q.pop();    Dis[s]=0;    vis[s]=1;    q.push(s);    while(q.size()){        int v=q.front(); q.pop();        vis[v]=0;        for(int i=0;i<G2[v].size();i++){            Edge& e=G2[v][i];            if(Dis[e.to]>Dis[v]+e.dis){                Dis[e.to]=Dis[v]+e.dis;                if(!vis[e.to]){                    vis[e.to]=1;                    q.push(e.to);                }            }        }    }}/*int A_star_first(int s,int t,int k){    if(s==t) k++;    if(Dis[s]==max_dis) return -1;    int cont[maxn];    memset(cont,0,sizeof(cont));    priority_queue<Node>Q;    while(Q.size()) Q.pop();    Node u,v;    u.st=s;    u.g=0;    u.h=Dis[s];    Q.push(u);    while(Q.size()){        u=Q.top(); Q.pop();        cont[u.st]++;        if(cont[u.st]>k) continue;    //当前点如果经过的次数大于k,很明显就不符合了。        if(cont[t]==k) return u.g;        for(int i=0;i<G1[u.st].size();i++){            Edge& e=G1[u.st][i];            v.st=e.to;            v.g=u.g+e.dis;            v.h=Dis[e.to];            Q.push(v);        }    }    return -1;}*/int A_star_second(int s,int t,int k){    if(s==t) k++;    if(Dis[s]==max_dis) return -1;    priority_queue<Node>Q;    while(Q.size()) Q.pop();    Node u,v;    int cnt=0;    u.st=s;    u.g=0;    u.h=Dis[u.st];    Q.push(u);    while(Q.size()){        u=Q.top(); Q.pop();        if(u.st==t) cnt++;        if(cnt==k) return u.g;        for(int i=0;i<G1[u.st].size();i++){            Edge& e=G1[u.st][i];            v.st=e.to;            v.g=u.g+e.dis;            v.h=Dis[v.st];            Q.push(v);        }    }    return -1;}int main(){    scanf("%d%d",&N,&M);    for(int i=0;i<M;i++){        scanf("%d%d%d",&A,&B,&T);        G1[A].push_back(Edge(B,T));        G2[B].push_back(Edge(A,T));    }    scanf("%d%d%d",&s,&t,&k);    spfa(t);    //dijkstra(t);    //dij(t);    int ans=A_star_second(s,t,k);    printf("%d\n",ans);    return 0;}

数组代码:

#include<map>#include<queue>#include<stack>#include<cmath>#include<cctype>#include<ctime>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxv = 1000 + 5;const int maxn = 100000 + 5;const int max_dis = 99999999;struct Edge{    int to;    int dis;    int next;};struct Node{    int st;    int g,h;    friend bool operator<(Node x,Node y){        return x.g+x.h>y.g+y.h;    }};int N,M;int A,B,T;int s,t,k;int Dis[maxv];int vis[maxv];Edge G1[maxn];Edge G2[maxn];int num1,num2;int head1[maxv],head2[maxv];typedef pair<int,int>P;void add1(int a,int b,int c){    G1[num1].to=b;    G1[num1].dis=c;    G1[num1].next=head1[a];    head1[a]=num1++;}void add2(int a,int b,int c){    G2[num2].to=b;    G2[num2].dis=c;    G2[num2].next=head2[a];    head2[a]=num2++;}void spfa(int s){    fill(Dis+1,Dis+N+1,max_dis);    memset(vis,0,sizeof(vis));    queue<int>q;    while(q.size()) q.pop();    Dis[s]=0;    vis[s]=1;    q.push(s);    while(q.size()){        int v=q.front(); q.pop(); //cout<<v<<endl;        vis[v]=0;        for(int k=head2[v];k>-1;k=G2[k].next){            if(Dis[G2[k].to]>Dis[v]+G2[k].dis){                Dis[G2[k].to]=Dis[v]+G2[k].dis;                if(!vis[G2[k].to]){                    vis[G2[k].to]=1;                    q.push(G2[k].to);                }            }        }    }//cout<<"**********"<<endl;}int A_star(int s,int t,int k){    if(s==t) k++;    if(Dis[s]==max_dis) return -1;    priority_queue<Node>Q;    while(Q.size()) Q.pop();    Node u,v;    int cnt=0;    u.st=s;    u.g=0;    u.h=Dis[u.st];    Q.push(u);    while(Q.size()){        u=Q.top(); Q.pop();        if(u.st==t) cnt++;        if(cnt==k) return u.g;        for(int i=head1[u.st];i>-1;i=G1[i].next){            v.st=G1[i].to;            v.g=u.g+G1[i].dis;            v.h=Dis[v.st];            Q.push(v);        }    }    return -1;}int main(){    memset(head1,-1,sizeof(head1));    memset(head2,-1,sizeof(head2));    num1=0; num2=0;    scanf("%d%d",&N,&M);    for(int i=0;i<M;i++){        scanf("%d%d%d",&A,&B,&T);        add1(A,B,T);        add2(B,A,T);    }    scanf("%d%d%d",&s,&t,&k);    spfa(t);    int ans=A_star(s,t,k);    printf("%d\n",ans);    return 0;}


0 0
原创粉丝点击