Poj 2449 第k短路

来源:互联网 发布:sap创建物料主数据 编辑:程序博客网 时间:2024/06/05 07:37

题目;
http://poj.org/problem?id=2449
题目要求;
给定图,起点终点,求第k短路
*算法:**A+spfa
流程:
反向建图,spfa预先处理出每个节点到终点的最短路h[i];h<=h*
在这里h=h*
设g[i]为从起点到节点经过的路径长度;g不是最短路;
类似迪杰斯塔拉,将堆的比较对象由g变为g+h;
当终点第k次被取出,该节点状态即答案;
正确性证明:
g+h 为从起点到终点经过节点i的最短路;
从起点开始遍历到达的节点,放入堆中后,堆顶元素一定是起点到终点最短路上的点,再以该节点i为起点遍历,一定能得到一个节点x,使得g[x]+h[x]=g[i]+h[i],即x也是最短路上的点,此时x也一定在堆顶,直到终点,堆顶元素的状态都是g[i]+h[i] (最短路),然后堆顶状态必为第2短路;
类推,第一次拿出终点,一定是终点的最短路,第k次拿出,一定是第k短路;

注意:
1.s==t时,k要加1 (除去路径长度等于0)。
2.路径不同,长度相同的路要重复计数。

#include<iostream>#include<cstdio>#include<algorithm>#include<queue>#include<vector>#include<cstring>using namespace std;const int N=1000+50;int n,m,s,t,k,last,cnt,x,y,z;int h[N];bool inq[N];struct node{    int a,g,h;};vector<int> tu[N],tu2[N],cost[N],cost2[N];queue<int> Q;priority_queue<node> q; bool operator < (node a,node b){    return a.g+a.h>b.g+b.h;}void build(int f,int t,int v){    tu[f].push_back(t);    tu2[t].push_back(f);    cost[f].push_back(v);    cost2[t].push_back(v);    return ;}void spfa(int x){    h[x]=0;    Q.push(x);    inq[x]=1;    while(!Q.empty()){        int u=Q.front();        Q.pop();        inq[u]=0;        for(int i=0;i<tu2[u].size();i++){            int v=tu2[u][i];            if(h[v]>h[u]+cost2[u][i]){                h[v]=h[u]+cost2[u][i];                if(!inq[v]){                    Q.push(v);                    inq[v]=1;                }            }        }    }    return ;}int done(){    if(s==t) k++;    if(h[s]==1e9+7) return -1;    q.push((node){s,0,h[s]});    while(!q.empty()){        node u=q.top();        q.pop();        int x=u.a;        if(x==t){                cnt++;                last=u.g+u.h;                if(cnt==k) return last;        }        for(int i=0;i<tu[x].size();i++){            int v=tu[x][i];            q.push((node){v,u.g+cost[x][i],h[v]});        }    }    return -1;}void init(){    while(!Q.empty()) Q.pop();    while(!q.empty()) q.pop();    for(int i=1;i<=n;i++){        tu[i].clear();        tu2[i].clear();        cost[i].clear();        cost2[i].clear();        inq[i]=0;        h[i]=1e9+7;    }    last=0;    cnt=0;}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        init();        for(int i=1;i<=m;i++){        scanf("%d%d%d",&x,&y,&z);        build(x,y,z);        }        scanf("%d%d%d",&s,&t,&k);        spfa(t);        int ans=done();            printf("%d\n",ans);    }    return 0;}
原创粉丝点击