POJ 2449-Remmarguts' Date(A*+spfa)

来源:互联网 发布:mysql date add 1 day 编辑:程序博客网 时间:2024/06/07 18:02
Remmarguts' Date
Time Limit: 4000MS Memory Limit: 65536KTotal Submissions: 25391 Accepted: 6930

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 21 2 52 1 41 2 2

Sample Output

14

Source

POJ Monthly,Zeyuan Zhu

题意:
   给你n个点,m条路。然后再给你起点s,终点t,求k短路。而且题目要求s==t时中间也要有点,不能只是起点与终点。

第一次学习A*算法,遇到了许多问题,spfa不会,那个前向星弄了好久才明白。解决了spfa之后,Astar函数很快就看明白了。其实A*有点像是反向的spfa吧,不过它是要每次都是从路径最小的去拓展的,感觉像是恶心的暴力每个点然后再存起来,而速度能这麽快完全是优先队列的功劳,那个f = g+v;其实就是贪心的表达式啊。

AC代码:

#include<iostream>#include<functional>#include<algorithm>#include<cstring>#include<string>#include<vector>#include<cstdio>#include<queue>#include<cmath>#include<map>using namespace std;#define CRL(a) memset(a,0,sizeof(a))#define QWQ ios::sync_with_stdio(0)#define inf 0x3f3f3f3ftypedef unsigned long long LL;typedef  long long ll;const int T = 200000+50;const int mod = 1000000007;int n,m,c,s,e,k;struct node{int v,next,w;//尾端点,相同头端点的上一条边存在的数组号,尾端点的权值}e1[T],e2[T];//正向与反向存数据struct Node{int f,g,v;//f代表f函数,g代表g函数,v代表当前所在的点bool operator<(const Node& b)const{return f>b.f||(f==b.f&&g>b.g);}};int head[T],tail[T];//前向星辅助数组1,辅助数组2int dis[1000+50];//节点的值bool vis[1000+50];//标记数组void Init()//初始化数组{c = 0;fill(head,head+T,-1);fill(tail,tail+T,-1);}void add(int x,int y,int w)//前向星存储{e1[c].v = y,e1[c].w = w;e1[c].next = head[x];head[x] = c;e2[c].v = x,e2[c].w = w;e2[c].next = tail[y];tail[y] = c++;}void spfa()//最短路{fill(dis,dis+1050,inf);fill(vis,vis+1050,false);queue<int> q;q.push(e);//开始松弛点dis[e] = 0;while(!q.empty()){int u = q.front();q.pop();vis[u] = 0;/*重新赋值为0,因为其它点也有可能要用到这个点,但用了这个点的就不会再用这个点 因为要是最短的路程,重复用一个点是不能有最短的路径的。*/for(int i=tail[u];~i;i=e2[i].next){//搜索相同起点的所有不同终点的值int v = e2[i].v;int w = e2[i].w;if(dis[v]>dis[u]+w){//如果起点+i这个点是比现在的起点小,更新dis[v] = dis[u]+w;if(!vis[v]){//没标记就要标记且记录下这个点然后继续松弛q.push(v);vis[v] = 1;}}}}}int Astar()//A*{int cnt = 0;//记录第几短priority_queue<Node> Q;if(s==e)k++;//题目要求必须要走过路径,不能呆在原地就是终点if(dis[s]==inf)return -1;//s不可达直接退出Node t,tt;t.v = s,t.g = 0,t.f = t.g + dis[s];//当前点的值,估价函数值,总的值Q.push(t);while(!Q.empty()){tt = Q.top(),Q.pop();if(tt.v==e){//第cnt次找到终点,肯定在前面找的数越小(优先队列)cnt ++;if(cnt==k)return tt.g;}//以点s为起点的数都拓展一次for(int i=head[tt.v];~i;i=e1[i].next){t.v = e1[i].v;t.g = tt.g + e1[i].w;//反向值t.f = t.g + dis[t.v];//总的权值Q.push(t);}}return -1;}int main(){#ifdef zsc    freopen("input.txt","r",stdin);#endif    int i,j;    while(~scanf("%d%d",&n,&m))    {int u,v,w;Init();for(i=1;i<=m;++i){scanf("%d%d%d",&u,&v,&w);add(u,v,w);}scanf("%d%d%d",&s,&e,&k);spfa();printf("%d\n",Astar());    }    return 0;}


1 0