【模板】POJ 2449 K短路(A*+dijkstra)

Remmarguts’ Date
Time Limit: 4000MS Memory Limit: 65536K
Total Submissions: 28521 Accepted: 7746
Description
“Good man never makes girls wait or breaks an appointment!” said the mandarin duck father. Softly touching his little ducks’ head, he told them a story.
“Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission.”
“Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)”
Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister’s help!
DETAILS: UDF’s capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince’ current place. M muddy directed sideways connect some of the stations. Remmarguts’ path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.
Input
The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T.
The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).
Output
A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output “-1” (without quotes) instead.
Sample Input
2 2
1 2 5
2 1 4
1 2 2
Sample Output
14
Source
POJ Monthly,Zeyuan Zhu

題目大意:求K短路
思路:
由於堆優化dijkstra貪心+終點的出堆次數就爲次數短路 我們可以記一個cnt記錄出堆次數 判斷一下得到答案
但是 這樣會TLE 因爲我們這一算法的複雜度與k和n相關
我們用A*優化,A*算法可以改變搜索範圍讓我們更快得到想要的答案
A*:公式表示爲: f(n)=g(n)+h(n)
其中 f(n) 是從初始點經由節點 n 到目標點的估價函數,
g(n) 是在狀態空間中從初始節點到 n 節點的實際代價,
h(n) 是從 n 到目標節點最佳路徑的估計代價。
即估價函數 = 當前值 + 當前位置到終點的距離
保證找到最短路徑(最優解的)條件,關鍵在於估價函數 f(n)的選取:
一、估價值 h(n)<= n 到目標節點的距離實際值,這種情況下,搜索的點數多,搜索範圍大,效率低。但能得到最優解。
二、 如果 h(n)=d(n),即距離估計 h(n)等於最短距離,那麼搜索將嚴格沿着最短路徑進行, 此時的搜索效率是最高的。
三、如果 h(n) > d(n),搜索的點數少,搜索範圍小,效率高,但不能保證得到最優解。
f*(n)=g*(n) +h*(n)
f*(n) :從初始節點 S0 出發,經過節點 n 到達目標節點的最小步數 (真實值)。
g*(n): 從 S0 出發,到達 n 的最少步數(真實值)
h*(n): 從 n 出發,到達目標節點的最少步數(真實值)
估價函數 f(n)則是 f*(n)的估計值。
我們怎麼來確定真正的最短的長度呢?
SPFA!
因爲題目是一個有向圖,那麼我們可以建一個反向圖,來記錄一下終點到起點的最短路, 這樣我們的估價就有一個準確的參考了,最起碼用SPFA估價會我們的答案會更接近正解而不是遠離它。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 233333;
int h[maxn],n,m,ss,tt,k;
bool vis[maxn],flag;
int tot1,fst1[maxn],nxt1[maxn];
int tot,fst[maxn],nxt[maxn];
struct heap
{
    int id;
    int g;
    bool operator < (const heap &hah)const
    {
        return g + h[id] > hah.g + h[hah.id];
    } 
};
struct Edge{
    int from,to,cost;
}es[maxn],es1[maxn];

void build(int f,int t,int d)
{
    es[++tot] = (Edge){f,t,d};
    nxt[tot] = fst[f];
    fst[f] = tot; 
} 

void build1(int f,int t,int d)
{
    es1[++tot1] = (Edge){f,t,d};
    nxt1[tot1] = fst1[f];
    fst1[f] = tot1; 
} 

queue<int>q1;
void spfa()
{
    memset(h,0x3f,sizeof(h));
    q1.push(tt);
    h[tt] = 0;
    while(!q1.empty())
    {
        int u = q1.front();
        vis[u] = 0;
        q1.pop();
        for(int i = fst1[u];i;i = nxt1[i])
        {
            int v = es1[i].to;
            if(h[v] > h[u] + es1[i].cost)
            {
                h[v] = h[u] + es1[i].cost;
                if(!vis[v])
                {
                    vis[v]=1;
                    q1.push(v);
                }
            }
        }
    }
}
priority_queue<heap>q;
void Astar() 
{
    q.push((heap){ss,0});
    int cnt = 0;
    while(!q.empty())
    {
        heap u = q.top();
        q.pop();
        if(u.id == tt)
        {
            cnt ++;
            if(cnt == k)
            {
                flag = 1;
                printf("%d",u.g);
                return;
            }
        }
        for(int i = fst[u.id];i;i = nxt[i])
        {
            int v = es[i].to;
            q.push((heap){v,u.g + es[i].cost});
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a,b;
        int c;
        scanf("%d%d%d",&a,&b,&c);
        build(a,b,c);
        build1(b,a,c);
    }
    scanf("%d%d%d",&ss,&tt,&k);
    if(ss == tt) k++;
    spfa();
    Astar();
    if(!flag) puts("-1");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章