您的位置:首页 > 其它

poj 2449( k 短路 spfa+A*来求解)

2011-10-03 21:19 260 查看
看到了一个讲解k短路的感觉不错。。。。。

对于A* ,估价函数 = 当前值+当前位置到终点的距离,即 F(p)=g(p)+h(p),每次扩展估价函数值中最小的一个。对于k短路来说,g(p)为当前从s到p所走的长度,h(p)为从p到 t 的最短路的长度,则F(p)的意义就是从s按照当前路径走到 p 后要走到终点 t 一共至少要走多远。也就是说我们每次的扩展都是有方向的扩展,这样就可以提高求解速度和降低扩展的状态数目。为了加速计算,h(p)需要从A*搜索之前进行预处理,只要将原图的所有边反向,再从终点
t 做一次单源最短路径就可以得到每个点的h(p)了。

还有就是这个题意说是t到s的k短路。。但样例给的是s到t的所以就在写程序的时候求s到t的就可以了。。囧。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define inf 1<<30
#define cc(m,v) memset(m,v,sizeof(m))
#define M 100005

struct node {
int v, g, f, next; // f=g+h
bool operator<(const node & t) const {
if (t.f == f) return t.g < g;
return t.f<f;
}
} edge[M], edge1[M];
int head[1005], p, head1[1005], n, dis[1005];

void spfa(int s) {
int u, v, i, j, cot[1005];
queue<int> q;
bool vis[1005];
for (i = 0; i <= n; i++) dis[i] = inf, cot[i]=0, vis[i]=0;
vis[s] = 1, dis[s] = 0, q.push(s);
while (!q.empty()) {
u = q.front(),q.pop(), vis[u] = 0, cot[u]++;
if(cot[u]>=n) return ;
for (j = head1[u]; j != -1; j = edge1[j].next)
if (dis[v=edge1[j].v] > dis[u] + edge1[j].g) {
dis[v]=dis[u]+edge1[j].g;
if(!vis[v])
vis[v] = 1, q.push(v);
}
}
}

int a_star(int s, int t, int k) {
int cnt = 0, i;
struct node e, ne;
priority_queue<node> que;
if (s == t) k++;
if (dis[s] == inf) return -1;
e.v = s, e.g = 0, e.f = e.g + dis[e.v];
que.push(e);
while (!que.empty()) {
e = que.top(), que.pop();
if (e.v == t) {
cnt++;
if (cnt == k) return e.g;
}
for (i = head[e.v]; i != -1; i = edge[i].next) {
ne.v = edge[i].v, ne.g = e.g + edge[i].g;
ne.f = ne.g + dis[ne.v], que.push(ne);
}
}
return -1;
}

void ainit() {
p = 0, cc(head, -1), cc(head1, -1);
}

void addedge(int u, int v, int w) {
edge[p].v = v, edge[p].g = w, edge[p].next = head[u], head[u] = p;
edge1[p].v = u, edge1[p].g = w, edge1[p].next = head1[v], head1[v] = p++;
}

int main() {
int s, m, t, u, v, w, i, k;
while (scanf("%d%d", &n, &m) != -1) {
ainit();
for (i = 1; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
scanf("%d%d%d", &s, &t, &k);
spfa(t);
printf("%d\n", a_star(s, t, k));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: