poj2449

题意:给定一个图,求起点到终点的第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要++,不明白为啥。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
#include
< queue >
using namespace std;

#define V 1005
#define E 1000005

int n, m, s, t, k;
#define typec int
// type of cost
const typec inf = 0x3f3f3f3f ;
// max of cost
typec cost[E], dist[V];
int e, pnt[E], nxt[E], head[V], prev[V], vis[V];
int pnt2[E], nxt2[E], head2[V], prev2[V], cost2[E];

struct pqnode
{
int v, dist;
pqnode(
int vv = 0 , typec cc = 0 ) :
v(vv), dist(cc)
{
}
};

struct qnode
{
int v;
typec c;
qnode(
int vv = 0 , typec cc = 0 ) :
v(vv), c(cc)
{
}
bool operator < ( const qnode & r) const
{
return c > r.c;
}
};

bool operator < ( const pqnode & a, const pqnode & b)
{
return a.dist + dist[a.v] > b.dist + dist[b.v];
}

void dijkstra( int n, const int src)
{
qnode mv;
int i, j, k, pre;
priority_queue
< qnode > que;
vis[src]
= 1 ;
dist[src]
= 0 ;
que.push(qnode(src,
0 ));
for (pre = src, i = 1 ; i < n; i ++ )
{
for (j = head[pre]; j != - 1 ; j = nxt[j])
{
k
= pnt[j];
if (vis[k] == 0 && dist[pre] + cost[j] < dist[k])
{
dist[k]
= dist[pre] + cost[j];
que.push(qnode(pnt[j], dist[k]));
prev[k]
= pre;
}
}
while ( ! que.empty() && vis[que.top().v] == 1 )
que.pop();
if (que.empty())
break ;
mv
= que.top();
que.pop();
vis[pre
= mv.v] = 1 ;
}
}

inline
void addedge( int u, int v, typec c)
{
pnt[e]
= v;
cost[e]
= c;
nxt[e]
= head[u];
head[u]
= e ++ ;
}

inline
void addedge2( int u, int v, typec c)
{
pnt2[e]
= v;
cost2[e]
= c;
nxt2[e]
= head2[u];
head2[u]
= e ++ ;
}

void input()
{
memset(head,
- 1 , sizeof (head));
memset(vis,
0 , sizeof (vis));
memset(prev,
- 1 , sizeof (prev));
memset(head2,
- 1 , sizeof (head2));
memset(prev2,
- 1 , sizeof (prev2));
scanf(
" %d%d " , & n, & m);
for ( int i = 0 ; i < n; i ++ )
dist[i]
= inf;
for ( int i = 0 ; i < m; i ++ )
{
int a, b, c;
scanf(
" %d%d%d " , & a, & b, & c);
a
-- ;
b
-- ;
addedge2(a, b, c);
addedge(b, a, c);
}
scanf(
" %d%d%d " , & s, & t, & k);
s
-- ;
t
-- ;
if (s == t)
k
++ ;
}

int astar()
{
memset(vis,
0 , sizeof (vis));
priority_queue
< pqnode > pq;
pq.push(pqnode(s,
0 ));
while ( ! pq.empty())
{
pqnode pre
= pq.top();
pq.pop();
vis[pre.v]
++ ;
if (vis[pre.v] == k)
return pre.dist + dist[pre.v];
for ( int i = head2[pre.v]; i != - 1 ; i = nxt2[i])
if (vis[pnt2[i]] <= k)
pq.push(pqnode(pnt2[i], pre.dist
+ cost2[i]));
}
return - 1 ;
}

int main()
{
// freopen("t.txt", "r", stdin);
input();
dijkstra(n, t);
printf(
" %d\n " , astar());
return 0 ;
}

你可能感兴趣的:(poj)