POJ 2449 Remmarguts' Date【K短路问题,A*、dijkstra】

时间:2021-11-24 09:42:36


POJ 2449 Remmarguts' Date
http://poj.org/problem?id=2449
算法核心:A*、dijkstra
大意:求有向图中从s到t的k短路
分析:
1.用dijkstra逆向计算出所有点到t的最短距离dis[i]
2.建立估价函数 f(i)= g(i)+h(i)
  其中g(i)为从s到i的实际距离,h(i)为从i到t的最短路dis[i]
3.使用上述估计函数用A*算法从s点出发BFS全图,用visited[i]表示点i的出队次数。
  当visited[i]=k时,即找到从s到t的k短路为f(i)
  其间若visited[i]>k则放弃该点

4.注意:若s==t,需 k+1;

POJ 2449 Remmarguts' Date【K短路问题,A*、dijkstra】POJ 2449 Remmarguts' Date【K短路问题,A*、dijkstra】View Code
#include < stdio.h >
#include
< string .h >
#include
< queue >
using namespace std;
const int N = 1000 + 1 ;
const int M = 100000 + 1 ;
struct Edge
{
int from,to;
int dis;
Edge
* next;
}
* ed[N],edge[M], * re[N],redge[M];
int ednum;
int dis[N];
int visited[N];
void init( int n)
{
int i;
for (i = 0 ;i < n;i ++ )
{
ed[i]
= NULL;
re[i]
= NULL;
}
}
void addEdge( int from, int to, int dis)
{
Edge
* ptr = & edge[ednum];
ptr
-> from = from;
ptr
-> to = to;
ptr
-> dis = dis;
ptr
-> next = ed[from];
ed[from]
= ptr;
}

void addRedge( int from, int to, int dis)
{
Edge
* ptr = & redge[ednum];
ptr
-> from = from;
ptr
-> to = to;
ptr
-> dis = dis;
ptr
-> next = re[from];
re[from]
= ptr;
}

struct dnode // dijkstra()优先队列中使用的节点
{
int v,len; // 记录从出发点到节点v的长度
bool operator < ( const dnode & A) const
{
return A.len < len;
}
};

void dijkstra( int s, int n) // 计算各点到终点的距离
{
memset(visited,
0 , sizeof (visited));
memset(dis,
- 1 , sizeof (dis));
priority_queue
< dnode > Q;
dnode cur,next;
cur.len
= 0 ;
cur.v
= s;
Q.push(cur);
dis[s]
= 0 ;
int vnum = 0 ; // 已访完的节点数
while ( ! Q.empty())
{
cur
= Q.top();

Q.pop();
if (visited[cur.v]) continue ;
visited[cur.v]
= 1 ;
vnum
++ ;
if (vnum == n) return ;
for (Edge * ed = re[cur.v];ed != NULL;ed = ed -> next)
{
if (visited[ed -> to] == 0 )
{
if (dis[ed -> to] ==- 1 || dis[ed -> to] > cur.len + ed -> dis)
{
next.len
= cur.len + ed -> dis;
dis[ed
-> to] = next.len;
next.v
= ed -> to;
Q.push(next);
}
}
}

}

}

struct anode // astar()优先队列中的节点
{
int to; // 记录从出发点到当前节点的距离
int len;
bool operator < ( const anode & A) const
{
if (dis[A.to] ==- 1 ) return false ;
if (dis[to] ==- 1 ) return true ;
return A.len + dis[A.to] < len + dis[to]; // 估计函数的使用
}
};
int aStar( int from, int to, int k)
{
memset(visited,
0 , sizeof (visited));

priority_queue
< anode > Q;
anode cur,next;
if (from == to)k ++ ; // 两点重合时按题意加1
cur.len = 0 ;
cur.to
= from;
Q.push(cur);
while ( ! Q.empty())
{
cur
= Q.top();
// printf("%d\n",cur.len);
Q.pop();
if (visited[cur.to] == k) return cur.len + dis[cur.to];
if (visited[cur.to] > k) continue ;
visited[cur.to]
++ ;
if (visited[to] == k) return cur.len;

for (Edge * ptr = ed[cur.to];ptr;ptr = ptr -> next)
{
next.len
= cur.len + ptr -> dis;
next.to
= ptr -> to;
Q.push(next);
}

}
return - 1 ;
}
int main()
{
int n,m;
while (scanf( " %d%d " , & n, & m) != EOF)
{
init(n);
ednum
= 0 ;
while (m -- )
{
int a,b,t;
scanf(
" %d%d%d " , & a, & b, & t);
a
-- ;
b
-- ;
addEdge(a,b,t);
addRedge(b,a,t);
ednum
++ ;
}
int s,t,k;
scanf(
" %d%d%d " , & s, & t, & k);
s
-- ,t -- ;
dijkstra(t,n);
// for(int i=0;i<n;i++)
// printf("%d\n",dis[i]);

if (dis[s] ==- 1 )printf( " -1\n " );
else
printf(
" %d\n " ,aStar(s,t,k));
}
return 0 ;
}