POJ 2449 Remmarguts' Date

经典的第K短路,A*函数主要是估值函数的设计与分析,这个需要一定的经验,似乎启发式函数在ACM/ICPC中很少用到哦!

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

const int MAXN = 1010;
const int MAXM = 100010;
const int INF = 0x3f3f3f3f;

int first[MAXN], d[MAXN];
int first2[MAXN];

int n, m;
int cnt;
int s, e, k;

struct Edge
{
	int v, next, w;
	int f, g; //f = g + h;
	bool operator < (const Edge &a) const
	{
		if(a.f == f) return a.g < g;
		return a.f < f;
	}
}edge[MAXM], edge2[MAXM];

inline void init()
{
	cnt = 0;
	memset(first, -1, sizeof(first));
	memset(first2, -1, sizeof(first2));
}

inline void read_graph(int u, int v , int w)
{
	edge[cnt].v = v, edge[cnt].g = w;
	edge[cnt].next = first[u], first[u] = cnt;
	edge2[cnt].v = u, edge2[cnt].w = w;
	edge2[cnt].next = first2[v], first2[v] = cnt++;
} //建立正、反向图 

void spfa(int src)
{
	queue<int> q;
	bool inq[MAXN] = {0};
	for(int i = 1; i <= n; i++) d[i] = (i == src)? 0:INF;
	q.push(src);
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		inq[x] = 0;
		for(int e = first2[x]; e != -1; e = edge2[e].next)
		{
			int v = edge2[e].v, w = edge2[e].w;
			if(d[v] > d[x] + w)
			{
				d[v] = d[x] + w;
				if(!inq[v])
				{
					inq[v] = 1;
					q.push(v);
				}
			}
		}
	}
}

int A_STAR(int s, int e, int k)
{
	int tot = 0;
	priority_queue<Edge> Q;
	struct Edge cur, next;
	cur.v = s, cur.g = 0, cur.f = d[s];
	if(s == e) k++; //当终点与起点相同时,0路径不算在第K短路径中,所以加1 
	if(d[s] == INF) return -1;
	Q.push(cur);
	while(!Q.empty())
	{
		cur = Q.top(); Q.pop();
		int u = cur.v;
		if(u == e)
		{
			tot++;
			if(tot == k) return cur.g;
		}
		for(int e = first[u]; e != -1; e = edge[e].next)
		{
			int v = edge[e].v, g = edge[e].g;
			next.v = v, next.g = cur.g + g;
			next.f = next.g + d[v];
			Q.push(next);
		}
	}
	return -1;
}

inline void read_case()
{
	init();
	while(m--)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		read_graph(u, v, w);
	}
	scanf("%d%d%d", &s, &e, &k);	
}

void solve()
{
	read_case();
	spfa(e);
	int ans = A_STAR(s, e, k);
	printf("%d\n", ans);
}

int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		solve();
	}
	return 0;
}


你可能感兴趣的:(POJ 2449 Remmarguts' Date)