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 }

 

你可能感兴趣的:(poj)