poj 2449(A*+dijstra求k短路)

A*算法入门

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 }

 

posted @ 2012-08-30 23:23  Missa  阅读(2154)  评论(1编辑  收藏  举报