Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 26504 | Accepted: 7203 |
Description
"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 last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).
Output
Sample Input
2 2 1 2 5 2 1 4 1 2 2
Sample Output
14
以前对A*有所耳闻,看得懂但是不知道如何实现,然后通过这道题有了一点理解……,这题做了两遍,第一次是看着别人的代码写的,第二次隔了段时间自己按照自己的理解写了下1A,理解一个算法还是非常重要的……
A*以我的理解就是给搜索算法一个大致的导向,尽量不往不必要的方向去搜索,也许也是因此叫做启发式搜索算法,就拿普通BFS比较吧,也就是一个退化了的A*,没有任何的导向,完全按照压入队列的时间顺序进行搜索,比如一个任意一点都可以站立的地图,人在中间,而目的地在右上角,显然BFS在到达目的地之前一定会对地图中大部分包括跟目的地相反方向的那些地方都搜索过,即越走越远,但是BFS不知道这些,只知道一层一层地扩展,即使走反了,如果有用标记或者染色,会发现地图上大部分无用、完全不必要的地区都被标记或染色过……因此BFS在数据范围较大的时候是比较慢的
而A*不一样,比BFS多了一个估价(启发)函数。先引用别的博主的一段话
所谓A*就是启发式搜索..说白了就是给BFS搜索一个顺序使得搜索更加合理减少无谓的搜索..如何来确定搜索的顺序?..也就是用一个值来表示这个值为f[x]..每次搜索取f[x]最小的进行拓展...f[x]=h[x]+g[x]其中h[x]就是当前搜索时的实际代价...估价函数要小于是对当前点到目标的代价的估计..这个估计必须小于等于实际值~~否则会出错...A*的关键也就是构造g[x]..
在图的搜索里面构造g[x]用的比较多的是欧氏距离、曼哈顿距离、切比雪夫距离(这个比较高端感觉不太用的上……)上面的紫色字体非常重要,这就是为什么要用反向的SPFA来做这题的原因,因为反着从T的单源的最短路放到正向的就不一定是某一点Si的最短路了,就可以保证反着是一定小于等于实际值的。这题还有一个小坑点就是如果一开始起点就是终点,那必须要绕一圈再回来,即k短路不能一开始就为0,VIS数组也不需要,首先这是k短路,其次这是A*启发式的,不会无脑遍历……然后就差不多可以做了……
代码:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int M=100010;
const int N=10010;
struct info
{
int to;
int pre;
int dx;
};
struct A
{
int cur;
int g;
int h;
bool operator<(const A &b)const
{
return g+h>b.g+b.h;
}
};
info E[M],rE[M];
int head[M],rhead[M],d[N],cnt,rcnt;
priority_queue<pii>Q;
priority_queue<A>Qa;
void init()
{
MM(head,-1);
MM(rhead,-1);
MM(d,INF);
while (!Q.empty())
Q.pop();
while (!Qa.empty())
Qa.pop();
cnt=rcnt=0;
}
void add(info edge[],int &c,int Head[],int s,int t,int d)
{
edge[c].to=t;
edge[c].dx=d;
edge[c].pre=Head[s];
Head[s]=c++;
}
void spfa(int s)
{
d[s]=0;
Q.push(pii(-d[s],s));
while (!Q.empty())
{
int now=Q.top().second;
Q.pop();
for (int i=rhead[now]; ~i; i=rE[i].pre)
{
int v=rE[i].to;
if(d[v]>d[now]+rE[i].dx)
{
d[v]=d[now]+rE[i].dx;
Q.push(pii(-d[v],v));
}
}
}
}
int main(void)
{
int n,m,i,j,a,b,c,s,t,k;
while (~scanf("%d%d",&n,&m))
{
init();
for (i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
add(rE,rcnt,rhead,b,a,c);
add(E,cnt,head,a,b,c);
}
scanf("%d%d%d",&s,&t,&k);
spfa(t);
int r=-1;
A S;
S.cur=s;
S.g=0;
S.h=d[s];
Qa.push(S);
if(s==t)
k++;
while (!Qa.empty())
{
A now=Qa.top();
Qa.pop();
if(now.cur==t)
{
if(--k==0)
{
r=now.g;
break;
}
}
for (i=head[now.cur]; ~i; i=E[i].pre)
{
A Next=now;
int v=E[i].to;
Next.cur=v;
Next.g+=E[i].dx;
Next.h=d[v];
Qa.push(Next);
}
}
printf("%d\n",r);
}
return 0;
}