poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)

http://poj.org/problem?id=2449

Remmarguts' Date
Time Limit: 4000MS   Memory Limit: 65536K
Total Submissions: 18168   Accepted: 4984

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从t反向寻找最短路。然后使用A*算法,把f(i)=g(i) + h(i)。h(i)就是i点到t的最短距离。当某点出队次数达到k次的时候,结果为该点的当前路程+该点到t的最短距离。(我没有判断不连通的情况)

为什么这样做是对的呢?我们这样来思考,如果不实用最短路,而只使用A*那么t第x次出队的结果即为第x短路的距离。继而可以想到,从第一个出队次数达到x的点,沿着最短路走到t,一定是第x短路。

说实话我也没有完全理解。

另外注意s==t的情况,据说k要++,不明白为啥。

 

这个题用来测第k短路的模板真的再好不过了,累计我wa在这么几个地方:
1.起点和终点是同一点时一定要走,不能输出0;
2.用普通邻接矩阵的话要注意重边的问题(所以强烈推荐邻接表水所有题);

【code】:

  1 /**
  2 Judge Status:Accepted      Memory:9252K
  3 Time:204MS      Language:G++
  4 Code Length:2590B       Author:cj
  5 */
  6 
  7 #include<iostream>
  8 #include<cstdio>
  9 #include<queue>
 10 #include<algorithm>
 11 #include<string.h>
 12 
 13 #define N 1005
 14 #define M 200100
 15 #define INF 1000000000
 16 using namespace std;
 17 
 18 struct Edge
 19 {
 20     int v,next,c;
 21 }edge[M];
 22 
 23 struct Nod  //A*中的优先队列数据类型
 24 {
 25     int v,d,h;
 26 };
 27 
 28 struct Dj  //dijkstra中的优先队列数据类型
 29 {
 30     int u,dis;
 31 };
 32 
 33 bool operator < (Dj a,Dj b)  //dijkstra中的优先对队重载<号
 34 {
 35     return b.dis<a.dis;
 36 }
 37 
 38 bool operator < (Nod a,Nod b) //A*中的优先队列重载<号
 39 {
 40     return b.h+b.d<a.h+a.d;
 41 }
 42 
 43 int head[N];
 44 int tail[N];
 45 int dis[N];
 46 int visit[N];
 47 int edge_cnt;
 48 int cnt[N];
 49 
 50 void init()  //初始化
 51 {
 52     memset(head,-1,sizeof(head));
 53     memset(tail,-1,sizeof(tail));
 54     edge_cnt = 0;
 55     memset(visit,0,sizeof(visit));
 56     memset(cnt,0,sizeof(cnt));
 57 }
 58 
 59 void addEdge(int a,int b,int c)
 60 {
 61     edge[edge_cnt].v = b;
 62     edge[edge_cnt].c = c;
 63     edge[edge_cnt].next = head[a];
 64     head[a] = edge_cnt++;    //记录起始边
 65 
 66     edge[edge_cnt].v = a;
 67     edge[edge_cnt].c = c;
 68     edge[edge_cnt].next = tail[b];
 69     tail[b] = edge_cnt++;   //记录结束边
 70 }
 71 void Dijkstra(int n,int t)  //对于以各点为起点到t点的最短路径
 72 {
 73     priority_queue<Dj> p_q;
 74     Dj now,temp;
 75     int i;
 76     for(i=1;i<=n;i++)   dis[i]=INF;
 77     dis[t] = 0;
 78     temp.dis = 0;
 79     temp.u = t;
 80     p_q.push(temp);
 81     while(!p_q.empty())
 82     {
 83         temp = p_q.top();
 84         p_q.pop();
 85         if(visit[temp.u])   continue;
 86         visit[temp.u] = 1;
 87         for(i=tail[temp.u];i!=-1;i=edge[i].next)
 88         {
 89             int v = edge[i].v;
 90             if(dis[v]>dis[temp.u]+edge[i].c)
 91             {
 92                 dis[v]=dis[temp.u]+edge[i].c;
 93                 now.u = v;
 94                 now.dis = dis[v];
 95                 p_q.push(now);
 96             }
 97         }
 98     }
 99 }
100 
101 int Astar_Kth(int s,int t,int k)
102 {
103     Nod cur,nxt;
104     priority_queue<Nod> p_q;
105     cur.v = s;
106     cur.d = 0;
107     cur.h = dis[s];
108     p_q.push(cur);
109     while(!p_q.empty())
110     {
111         cur = p_q.top();
112         p_q.pop();
113         cnt[cur.v]++;
114         if(cnt[cur.v]>k)    continue;
115         if(cnt[t]==k)   return cur.d;
116         int i;
117         for(i=head[cur.v];i!=-1;i=edge[i].next)
118         {
119             int v = edge[i].v;
120             nxt.d = cur.d + edge[i].c;
121             nxt.v = v;
122             nxt.h = dis[v];
123             p_q.push(nxt);
124         }
125     }
126     return -1;
127 }
128 
129 
130 int main()
131 {
132     int n,m;
133     scanf("%d%d",&n,&m);
134     int i;
135     int a,b,c;
136     init();
137     for(i=0;i<m;i++)
138     {
139         scanf("%d%d%d",&a,&b,&c);
140         addEdge(a,b,c);
141     }
142     int s,t,k;
143     scanf("%d%d%d",&s,&t,&k);
144     if(s==t) k++;
145     Dijkstra(n,t);
146     printf("%d\n",Astar_Kth(s,t,k));
147     return 0;
148 }

 

posted @ 2013-08-16 16:28  crazy_apple  阅读(534)  评论(0编辑  收藏  举报