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

来源:互联网 发布:阿里云怎么升级配置 编辑:程序博客网 时间:2024/06/18 08:17

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<cstdio>#include<queue>using namespace std;const int maxn=100000*2;const int maxm=1500;const int inf=0x7fffffff;int h[maxm];struct heap{    int p;    int dis;    bool operator < (const heap &hah)const    {        return dis+h[p] > hah.dis+h[hah.p];    } };int n,m,ss,tt,k;priority_queue<heap>q;struct Edge{    int to;    int d;    int next;}edge[maxn],edge1[maxn];bool vis[maxm];int head[maxn],head1[maxn];int tot;void add(int f,int t,int d){    edge[++tot].to=t;    edge[tot].d=d;    edge[tot].next=head[f];    head[f]=tot;} int tot1;void add1(int f,int t,int d){    edge1[++tot1].to=t;    edge1[tot1].d=d;    edge1[tot1].next=head1[f];    head1[f]=tot1;} queue<int>q1;void spfa(){    for(int i=1;i<=n;i++)        h[i]=inf;    q1.push(tt);    h[tt]=0;    while(!q1.empty())    {        int x=q1.front();        vis[x]=0;        q1.pop();        for(int i=head1[x];i;i=edge1[i].next)        {            Edge e=edge1[i];            if(h[e.to]>h[x]+e.d)            {                h[e.to]=h[x]+e.d;                if(!vis[e.to])                {                    vis[e.to]=1;                    q1.push(e.to);                }            }        }    }}bool flag=false;void dij() {    q.push((heap){ss,0});    int cnt=0;    while(!q.empty())    {        heap p=q.top();        q.pop();        if(p.p==tt)        {            cnt++;            if(cnt==k)            {                flag=1;                printf("%d",p.dis);                return;            }        }        for(int i=head[p.p];i;i=edge[i].next)        {            int v=edge[i].to;            q.push((heap){v,p.dis+edge[i].d});        }    }}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);        add(a,b,c);        add1(b,a,c);    }    scanf("%d%d%d",&ss,&tt,&k);    if(ss==tt)        k++;    spfa();    dij();    if(!flag)        puts("-1");    return 0;}
0 0
原创粉丝点击