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.
"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).
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 }