poj2449 Remmarguts' Date 第K短路 A*

Remmarguts' Date
Time Limit: 4000MS   Memory Limit: 65536K
Total Submissions: 22226   Accepted: 6023

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

  求第K短路,如果没有输出-1。
  以前是听过A*,现在才学习了一下。

  来自百度百科:
A*(A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好。
公式表示为: f(n)=g(n)+h(n),
其中 f(n) 是从初始点经由节点n到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

  说简单点就是每个点有个值f(n),在优先队列中f值小的优先搜索。f=g+h。这道题里g是起始点到当前点走的步数,取h为当前点到终点的最短路。
  当h为0时就变成了BFS,也就是BFS是A*的一种特殊情况。
  可以自己想一下,如果在最短路上走,f不会变大,所以更可能优先被搜索,效率就会高。

  那么这道题先用dijkstra求出终点到其它点的最短路,然后用A*算法,对于每个点有g和h,加入优先队列,g+h小的优先。直到终点被加入优先队列K次。
  注意如果起点和终点相同,K要加1。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<queue>
#include<map>
using namespace std;

typedef pair<int,int> pii;

const int MAXN=1010;
const int MAXM=25;
const int MAXC=110;
const int MAXNODE=100010;
const int LOGMAXN=50;
const int INF=0x3f3f3f3f;

int N,M,S,E,K;
int d[MAXN];

struct Point{
    int u,d;
    bool operator < (const Point& rhs) const{
        return d>rhs.d;
    }
};
struct Edge{
    int u,v,dist;
};

struct Dijkstra{
    int n;
    int vis[MAXN];
    vector<int> G[MAXN];
    vector<Edge> edges;

    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void add_edge(int u,int v,int dist){
        edges.push_back((Edge){u,v,dist});
        int m=edges.size()-1;
        G[u].push_back(m);
    }
    void dijkstra(){
        priority_queue<Point> q;
        memset(d,INF,sizeof(d));
        memset(vis,0,sizeof(vis));
        d[E]=0;
        q.push((Point){E,0});
        while(!q.empty()){
            Point tmp=q.top();
            q.pop();
            int u=tmp.u;
            if(vis[u]) continue;
            vis[u]=1;
            int len=G[u].size();
            for(int i=0;i<len;i++){
                Edge& e=edges[G[u][i]];
                if(d[u]+e.dist<d[e.v]){
                    d[e.v]=d[u]+e.dist;
                    q.push((Point){e.v,d[e.v]});
                }
            }
        }
    }
}solver;

struct Point2{
    int u,g,h;
    bool operator < (const Point2& rhs) const{
        return g+h>rhs.g+rhs.h;
    }
};

struct Astar{
    int n;
    int cnt[MAXN];
    vector<int> G[MAXN];
    vector<Edge> edges;

    void init(int n){
        this->n-n;
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }
    void add_edge(int u,int v,int dist){
        edges.push_back((Edge){u,v,dist});
        int m=edges.size()-1;
        G[u].push_back(m);
    }
    int astar(int S,int E,int K){
        priority_queue<Point2> q;
        memset(cnt,0,sizeof(cnt));
        if(d[S]==INF) return -1;
        q.push((Point2){S,0,d[S]});
        while(!q.empty()){
            Point2 tmp=q.top();
            q.pop();
            int u=tmp.u,g=tmp.g,h=tmp.h;
            cnt[u]++;
            if(u==E&&cnt[u]>=K) return g;
            if(cnt[u]>K) continue;
            int len=G[u].size();
            for(int i=0;i<len;i++){
                Edge& e=edges[G[u][i]];
                if(d[e.v]!=INF) q.push((Point2){e.v,g+e.dist,d[e.v]});
            }
        }
        return -1;
    }
}solver2;

int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&N,&M)!=EOF){
        solver.init(N+1);
        solver2.init(N+1);
        int u,v,dist;
        while(M--){
            scanf("%d%d%d",&u,&v,&dist);
            solver.add_edge(v,u,dist);
            solver2.add_edge(u,v,dist);
        }
        scanf("%d%d%d",&S,&E,&K);
        if(S==E) K++;
        solver.dijkstra();
        printf("%d\n",solver2.astar(S,E,K));
    }
    return 0;
}


 

 

你可能感兴趣的:(poj2449 Remmarguts' Date 第K短路 A*)