POJ 2449(A*算法与最短路算法)

来源:互联网 发布:张大宇数据 编辑:程序博客网 时间:2024/06/05 23:50

题目描述:给定一个带权有向图,询问从起点到终点第k短路径长度,如果没有则输出-1。这个题目数据有特殊之处,就是如果起点与终点重合时,距离0并不算第一短最短路径。


A*算法:使用估值函数来进行搜索,f(n)=g(n)+h(n),其中f(n)表示状态起点经过状态n到状态终点的估值,g(n)为状态起点到状态n的距离值,h(n)为状态n到状态终点的距离值。之所以说f(n)是估值函数是因为,h(n)通常不是准确值而是估计值。该题的状态是(u,g,f)其中u表示当前在点u,且从状态起点到此状态的距离值为g,f是通过dis(u)+g计算得到。

其中dis(u)为点u到终点的最短距离。

每次扩展时使用f最小的状态。搜索时出现第k次终点t时,就能得出答案。

简单证明:f值最小即g+dis(u)最小,则当第一次出现终点t时,就是从起点到终点的最短路径。当舍弃最短路径后,继续扩展状态,可以想到当第二次出现终点t时,就是从起点到终点的第二短路径,所以可以求出第k小最短路径。


代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <queue>using namespace std;const int maxn=1005;const int maxe=100005;struct State{    int f;    int g;    int u;    bool operator<(const State b)const{        if(f==b.f)return g>b.g;        return f>b.f;    }};struct Edge{    int v;    int w;    int ne;}edge[maxe],reedge[maxe];int head[maxn],rehead[maxn];int dis[maxn],vis[maxn];int n,m;int cot;int s,t,k;void init(){    cot=0;    memset(head,-1,sizeof(head));    memset(rehead,-1,sizeof(rehead));}void addedge(int u,int v,int w){    edge[cot].v=v;    edge[cot].w=w;    edge[cot].ne=head[u];    head[u]=cot;    reedge[cot].v=u;    reedge[cot].w=w;    reedge[cot].ne=rehead[v];    rehead[v]=cot++;}void SPFA(){    queue<int>q;    memset(vis,0,sizeof(vis));    memset(dis,-1,sizeof(dis));    int u,v;    q.push(t);    vis[t]=true;    dis[t]=0;    while(!q.empty()){        u=q.front();        q.pop();        for(int i=rehead[u];~i;i=reedge[i].ne){            v=reedge[i].v;            if(dis[v]>dis[u]+reedge[i].w||dis[v]==-1){                dis[v]=dis[u]+reedge[i].w;                if(!vis[v]){                    q.push(v);                    vis[v]=true;                }            }        }        vis[u]=false;    }}int Astart(){    if(s==t)k++;    if(dis[s]==-1)return -1;    int cnt=0;    priority_queue<State>q;    State a,b;    a.g=0;a.u=s;a.f=a.g+dis[a.u];    q.push(a);    while(!q.empty()){        b=q.top();        q.pop();        if(b.u==t){            cnt++;            //printf("%d %d %d %d\n",b.f,b.g,b.u,dis[b.u]);            if(cnt==k)return b.g;        }        for(int i=head[b.u];~i;i=edge[i].ne){            a.g=b.g+edge[i].w;            a.u=edge[i].v;            a.f=a.g+dis[a.u];            q.push(a);        }    }    return -1;}int main(){    int u,v,w;    while(scanf("%d %d",&n,&m)==2){        init();        for(int i=0;i<m;i++){            scanf("%d %d %d",&u,&v,&w);            addedge(u,v,w);        }        scanf("%d %d %d",&s,&t,&k);        SPFA();        /*        for(int i=1;i<=n;i++){            printf("%d:%d\n",i,dis[i]);        }        */        printf("%d\n",Astart());    }    return 0;}


0 0
原创粉丝点击