现在的位置: 首页 > 综合 > 正文

poj2449 Remmarguts’ Date

2018年04月05日 ⁄ 综合 ⁄ 共 2294字 ⁄ 字号 评论关闭

典型的求k短路径的问题,有很多种算法,暂时试了试Dijkstra+A*算法

k短路径的相关问题看这里,尽管已经是2007年的文章了,但作者真的写得非常详细和全面。

下面是一个简化的算法流程。

/*
 * k短路径 Dijkstra+A*算法
 * 算法流程:
 * 1.将有向图的边反向后,Dijkstra求出任意节点到终点的最短路径 dis[i]
 * 2.优先队列 
 * 		struct
 * 		{
 * 			int v,l,d;
 * 		}priority_queue[10000];
 * 	v:结点编号
 * 	l:源点到v的距离
 * 	d:源点经过v的到终点的某一条路径的长度
 *  优先队列以l为权值排序
 * 3.v = s,l = 0,d = 0; 入队
 * 	 每次从优先队列中取出并去除l最小的结点
 * 	 遍历结点v的所有后继,计算d,l并入队,不判断v的后继结点是否在队列中

		for(i=head[k];i;i=edge[i].next)
		{
			q[++len].v = edge[i].v;
			q[len].d = dis[edge[i].v]+edge[i].d+q[l].l;
			q[len].l = q[l].l+edge[i].d;
			inq[len] = true;
			sum++;
		}
 * 4.第k次取出终点结点t,d即为第k短路径 
 *   可能出现同一长度的不同路径,都会被分别找出
 * */

/*
 * poj2449 AC
 * k短路径 Dijkstra+A*算法 266ms
 * 第一次用STL,还不是很熟悉,以前都是手写二叉堆的。
 * Dijkstra开始写错了,导致TLE,一天不写手生。
 * 题目要注意,当终点和起点相同时,最短路径不是0,必须走一圈回来。
 * */
#include<stdio.h>
#include<memory.h>
#include<queue>
#include<fstream>
#include<vector>
using namespace std;

#define INF 100000000
struct EDGE
{
	int v,t;
	long next;
}edge[100005],e[100005];
typedef struct 
{
	long len,d;
	int v;
}NODE;
struct cmp
{
	bool operator()(const NODE &t1,const NODE &t2)
	{
		return t1.d>t2.d;
	}
};
long head[1005],h[1005];
long n,m,tot,tot1;
int a,b,c;
long dis[1005];

void Dijkstra()
{
	bool vis[1005];
	NODE node,tmp;
	priority_queue<NODE,vector<NODE>,cmp> queue;

	long i,j;
	for(i=1;i<=n;i++)
	{
		vis[i] = false;
		dis[i] = INF;
	}
	dis[b] = 0;
	node.d= 0,node.v = b;
	queue.push(node);
	for(i=1;i<=n;i++)
	{
		node = queue.top();
		queue.pop();
		
		vis[node.v] = true;
		for(j=h[node.v];j;j=e[j].next)
			if(!vis[e[j].v] && dis[e[j].v]>dis[node.v]+e[j].t)
			{
				dis[e[j].v] = dis[node.v]+e[j].t;
				tmp.v = e[j].v;
				tmp.d= dis[e[j].v];
				queue.push(tmp);
			}
	}
	while(!queue.empty())
		queue.pop();
	return;
}

long a_star()
{
	NODE node,tmp;
	long i,num = 0;
	priority_queue<NODE,vector<NODE>,cmp> queue;
	node.len = 0,node.d = 0,node.v = a;
	queue.push(node);
	while(!queue.empty())
	{
		node = queue.top();
		queue.pop();
		if(node.v==b)
		{
			num++;
			if(num==c) return node.d;
		}
		for(i=head[node.v];i;i=edge[i].next)
		{
			tmp.v = edge[i].v;
			tmp.d = node.len+edge[i].t+dis[edge[i].v];
			tmp.len = node.len+edge[i].t;
			queue.push(tmp);
		}
	}
	return -1;
}

int main()
{
//	FILE* fin;
//	fin = fopen("d.in","r");
	scanf("%ld%ld",&n,&m);
//	fscanf(fin,"%ld%ld",&n,&m);
	int i,j,k,t;
	memset(head,0,sizeof(head));
	memset(h,0,sizeof(h));
	tot = tot1 = 0;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&j,&k,&t);
//		fscanf(fin,"%d%d%d",&j,&k,&t);
		edge[++tot].v = k,edge[tot].t = t,edge[tot].next = head[j],head[j] = tot;
		e[++tot1].v = j,e[tot1].t = t,e[tot1].next = h[k],h[k] = tot1;
	}
	scanf("%d%d%d",&a,&b,&c);
//	fscanf(fin,"%d%d%d",&a,&b,&c);
	if(a==b) c++;

	Dijkstra();
	long ans;
	ans = a_star();
	printf("%ld\n",ans);
	return 0;
}

抱歉!评论已关闭.