POJ - 2449 Remmarguts' Date (k短路)(A*)

题目链接

题意:求有向图从s点到t点的第k短路,每个点可以重复经过。

解法:建一个正向图和一个反向图,先用Dijkstra求出反向图中从t点到其他点的最短距离dis,再用A*算法求出第k短路。

A*求第k短路的方法:与Dijkstra算法类似,设结点nd(u,g)表示当前所在点为u且从s到u经过的长度为g的结点(路径),则以g+dis[u]为权值放进优先队列,每次选择权值最小的结点进行扩展,直至t点第k次出队。

算是A*算法的一道入门题吧。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 
 5 using namespace std;
 6 const int N=1000+10,M=1e5+10;
 7 const int inf=0x3f3f3f3f;
 8 struct E {
 9     int v,c,nxt;
10 } e[M<<1];
11 int head1[N],head2[N],dis[N],vis[N],ne;
12 int n,m;
13 
14 struct cmp {
15     bool operator()(int a,int b)const {
16         return dis[a]>dis[b];
17     }
18 };
19 
20 struct nd {
21     int u,g;
22     bool operator<(const nd& b)const {
23         return g+dis[u]>b.g+dis[b.u];
24     }
25 };
26 
27 void Dij(int s) {
28     priority_queue<int,vector<int>,cmp> q;
29     memset(vis,0,sizeof vis);
30     memset(dis,inf,sizeof dis);
31     dis[s]=0;
32     q.push(s);
33     while(!q.empty()) {
34         int u=q.top();
35         q.pop();
36         if(vis[u])continue;
37         vis[u]=1;
38         for(int i=head2[u]; ~i; i=e[i].nxt) {
39             int v=e[i].v,c=e[i].c;
40             if(dis[u]+c<dis[v]) {
41                 dis[v]=dis[u]+c;
42                 q.push(v);
43             }
44         }
45     }
46 }
47 
48 int Astar(int s,int t,int k) {
49     int cnt=0;
50     if(s==t)cnt--;
51     priority_queue<nd> q;
52     q.push({s,0});
53     while(!q.empty()) {
54         int u=q.top().u,g=q.top().g;
55         q.pop();
56         if(u==t)++cnt;
57         if(cnt==k)return g;
58         for(int i=head1[u]; ~i; i=e[i].nxt) {
59             int v=e[i].v,c=e[i].c;
60             q.push({v,g+c});
61         }
62     }
63     return -1;
64 }
65 
66 int main() {
67     memset(head1,-1,sizeof head1);
68     memset(head2,-1,sizeof head2);
69     ne=0;
70     scanf("%d%d",&n,&m);
71     while(m--) {
72         int u,v,c;
73         scanf("%d%d%d",&u,&v,&c);
74         e[ne]=(E) {v,c,head1[u]},head1[u]=ne++;
75         e[ne]=(E) {u,c,head2[v]},head2[v]=ne++;
76     }
77     int s,t,k;
78     scanf("%d%d%d",&s,&t,&k);
79     Dij(t);
80     printf("%d\n",Astar(s,t,k));
81     return 0;
82 }

 

posted @ 2019-01-12 19:47  jrltx  阅读(162)  评论(0编辑  收藏  举报