poj 2449(A*+dijstra求k短路)
A*算法是一种启发式的搜索,不是纯粹的盲目式搜索,A*算法中有个估价算法g(n),对于每个点而言,都有一个g(n)和h(n)来确定的f(n),实际上就是以f(n)为参考权值来确定搜索的方向,在这里,我们的h(n)表示的是从s点出发到n这个点现在走过的路径长度,而g(n)表示的是从n到e的最短长度的大小,那么就确定了搜索的优先性,这里的A*算法的估价函数g(n)是完美估价,搜索的方向一定是对的。
分析:
建图的时候建一个正向的一个反向的,反向的图利用dij求终点到每个点的最短路,即为搜索的估价函数。
注意的地方:
st==en 的时候必须k++ 因为题目要求必须走过路径。
详细见代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 #define inf 0x7ffffff 9 #define MAXN 1010 10 #define MAXM 100005 11 12 struct Edge 13 { 14 int u;//反向图的终止边 15 int v;//终止点 16 int c;//边权值 17 int next;//下一个节点 18 int next1;//反向边下一个节点 19 Edge(){} 20 Edge(int u,int v,int c):u(u),v(v),c(c){} 21 }p[MAXM]; 22 int head[MAXN];//链表头 23 int head1[MAXN];//反向 24 int e; //邻接表中边总数 25 int st,en,k;//起点,终点,第k短路 26 int n,m; 27 int dis[MAXN];//dis[v]表示的是终点到v的距离,即估价函数g 28 bool vis[MAXN]; 29 30 struct pro 31 { 32 int v,c;//v是终点,c是起点到v的距离 33 pro(){} 34 pro(int v,int c):v(v),c(c){} 35 bool operator < (const pro& a) const 36 { 37 return c+dis[v] > a.c+dis[a.v];//最小值优先队列 38 } 39 }; 40 41 void clear()//初始化 42 { 43 memset(head,-1,sizeof(head)); 44 memset(head1,-1,sizeof(head1)); 45 e=0; 46 } 47 void addEdge(int u,int v,int c)//加边 48 { 49 p[e]=Edge(u,v,c); 50 p[e].next1=head1[v];head1[v]=e; 51 p[e].next=head[u];head[u]=e++; 52 } 53 54 priority_queue<pro> que; 55 void dij(int src)//求估价函数 56 { 57 memset(vis,0,sizeof(vis)); 58 for(int i=1;i<=n;i++) 59 dis[i]=inf; 60 dis[src]=0; 61 while(!que.empty()) 62 que.pop(); 63 que.push(pro(src,0)); 64 while(!que.empty()) 65 { 66 pro cur = que.top(); 67 que.pop(); 68 if(vis[cur.v]) 69 continue; 70 vis[cur.v]=1; 71 for(int i=head1[cur.v];i+1;i=p[i].next1) 72 { 73 if(dis[p[i].u] > dis[cur.v] + p[i].c) 74 { 75 dis[p[i].u] = dis[cur.v] + p[i].c; 76 que.push(pro(p[i].u,0)); 77 } 78 } 79 } 80 } 81 82 int a_star(int src) 83 { 84 while(!que.empty()) 85 que.pop(); 86 que.push(pro(src,0)); 87 while(!que.empty()) 88 { 89 pro cur = que.top(); 90 que.pop(); 91 if(cur.v==en) 92 { 93 if(k>1)//相当于求k次最短路 94 k--; 95 else 96 return cur.c; 97 } 98 99 for(int i=head[cur.v];i+1;i=p[i].next)//将所有与u相连接的点都加入队列 100 que.push(pro(p[i].v,cur.c+p[i].c)); 101 } 102 return -1; 103 } 104 105 int main() 106 { 107 int u,v,c; 108 while(scanf("%d%d",&n,&m) != EOF) 109 { 110 clear(); 111 while(m--) 112 { 113 scanf("%d%d%d",&u,&v,&c); 114 addEdge(u,v,c); 115 } 116 scanf("%d%d%d",&st,&en,&k); 117 dij(en); 118 if(dis[st]==inf) 119 { 120 puts("-1"); 121 continue; 122 } 123 if(st == en) 124 k++; 125 printf("%d\n",a_star(st)); 126 } 127 return 0; 128 }