1. 程式人生 > >poj 2449 Remmarguts' Date【第K短路】

poj 2449 Remmarguts' Date【第K短路】

題目

題意:求 點s 到 點t 的 第 k 短 路的距離;

估價函式=當前值+當前位置到終點的距離

f(n)=g(n)+h(n);     g(n)表示g當前從s到p所走的路徑的長度,      h(n)‘啟發式函式’,表示為終點t到其餘一點p的路徑長度;

(1)將有向圖的所有邊反向,以原終點t為源點,求解t到所有點的最短距離;  (2)新建一個優先佇列,將源點s加入到佇列中;  (3)從優先順序佇列中彈出f(p)最小的點p,如果點p就是t,則計算t出隊的次數;  如果當前為t的第k次出隊,則當前路徑的長度就是s到t的第k短路的長度,演算法結束;  否則遍歷與p相連的所有的邊,將擴展出的到p的鄰接點資訊加入到優先順序佇列;

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;

const int Maxn = 10010;
const int INF = 1e9;

struct node{
    int to,val;
    node(){}
    node(int a,int b)
    {
        to = a; val = b;
    }
};

vector<node> adj[Maxn],_adj[Maxn];

int n,m,k;
bool vis[Maxn];
int dis[Maxn];

void AddEdge(int x,int y,int val)
{
    adj[x].push_back(node(y,val));
    _adj[y].push_back(node(x,val));//反向存圖
}
void Dijkstra(int s,int t)
{
    priority_queue<int, vector<int>,greater<int> > q;
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++)
        vis[i]=false,dis[i]=INF;
    vis[t]=true;dis[t]=0;q.push(t);
    int u,len;
    while(!q.empty())
    {
        u = q.top(); q.pop();
        len = _adj[u].size();
        for(int i=0;i<len;i++)
        {
            node v = _adj[u][i];
            if(dis[v.to]>dis[u]+v.val)
            {
                dis[v.to]=dis[u]+v.val;
                if(!vis[v.to])
                {
                    q.push(v.to);
                    vis[v.to]=true;
                }
            }
        }
        vis[u]= false;
    }
}
struct Anode{
    int h,g,id;
    Anode(int a,int b,int c){h=a;g=b;id=c;}
    bool operator < (Anode a) const{
        return h+g > a.h + a.g;
    }
};
priority_queue<Anode> Q;
int Astar(int s,int t)    //A*演算法
{
    while(!Q.empty()) Q.pop();
    Q.push(Anode(0,dis[s],s));
    int len,num;
    num=0;
    while(!Q.empty())
    {
        Anode u = Q.top();
        Q.pop();
        if(u.id==t) ++num;
        if(num>=k) return u.h;
        len = adj[u.id].size();
        for(int i=0;i<len;i++)
        {
            node v = adj[u.id][i];
            Q.push(Anode(u.h+v.val,dis[v.to],v.to));
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(int i=0;i<Maxn;i++)
            adj[i].clear(),_adj[i].clear();
        int x,y,v,s,t;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&v);
            AddEdge(x,y,v);
        }
        scanf("%d%d%d",&s,&t,&k);
        if(s==t) k++;
        Dijkstra(s,t);
        printf("%d\n",Astar(s,t));
    }
    return 0;
}
/*
2 2
1 2 5
2 1 4
1 2 2
*/