POJ 2449 Remmarguts' Date

题目大意:

        好男人决不能错过和女生的约会。

        从前有一个UDF(联合三角洲自由王国)王国,一天王国的邻居国家的公主Uyuw被派往UDF完成一项外交使命,而在这之前Uyuw已经通知过UDF的王子Remmarguts她将会到UDF首都的大厅中与王子商讨商业事宜,但是商讨能开展的条件就是王子必须通过k短路径到达大厅(公主并不想见王子,故意为其设置障碍)。出于对公主的倾心以及对国家商贸发展的重视王子决定前往。

        UDF首都共有N个驿站(1 ≤ N ≤ 1,000)和M条泥泞小路(都是单向的,1 ≤ M ≤ 100,000),S为王子的出发地点,T是目标地点(即大厅),为了走k短路径同一个驿站可能会经过两次或者两次以上,包括S和T。

        现有多个测例(测例数无上限),每个测例中都会给出N和M,驿站按1-N编号,每条路都会给出起点、终点和路上所花的时间t(1 ≤ t ≤ 100),最后给出起点S、终点T和第k短路径的k(1 ≤ k ≤ 1,000),对于每个测例都需要打印k短路径的长度(即总时间),如果k短路径不存在则打印-1即可。

题目链接

注释代码:

/*                   
 * Problem ID : POJ 2449 Remmarguts' Date
 * Author     : Lirx.t.Una                   
 * Language   : G++       
 * Run Time   : 657 ms                   
 * Run Memory : 8808 KB                   
*/ 

#pragma G++ optimize("O2")

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define	NIL				0
//infinity
//这里指k短路径的最大时间
//INF ≥ MAXSIDEWAYN × MAXT(单条路径的最大时间是100)
#define	INF				1000000000

//maximum number of stations
//站的最大数量
#define	MAXSTATIONN		1001
//maximum number of sideways
//有向路径的最大数量
#define	MAXSIDEWAYN		100001

using namespace std;

struct	Arc {

	int		u;
	int		v;
	int		t;//time,时间权值

	Arc(void) {}

	Arc( int xu, int xv, int xt ) :
		u(xu), v(xv), t(xt) {}
};

Arc		arc[MAXSIDEWAYN];
int		e;

int		head[MAXSTATIONN];
int		rhead[MAXSTATIONN];//reverse,逆图

int		next[MAXSIDEWAYN];
int		rnext[MAXSIDEWAYN];

int		stk[MAXSTATIONN];
bool	in[MAXSTATIONN];
int		top;

int		dp[MAXSTATIONN];//dp[i],i点到目标点的最短时间

struct	Node {

	int		ith;
	int		tot;//total time,从起始到该点所经过的总时间
	int		f;//f为估价函数,等于tot加上该店到目标点的单源最短路径

	Node(void) {}

	Node( int xith, int pst, int dt ) :
		ith(xith), tot( pst + dt ),
		f( tot + dp[xith] ) {}

	bool
	operator<(const Node &oth)
	const {
	
		return f > oth.f;
	}
};

void
addarc( int u, int v, int t ) {

	arc[e]   = Arc( u, v, t );

	next[e]	 = head[u];
	head[u]	 = e;

	//初始化逆图
	rnext[e] = rhead[v];
	rhead[v] = e++;
}

void
init( int n, int m ) {

	int		u, v;
	int		t;
	int		i;

	memset( head + 1, NIL, n * sizeof(int));
	memset( rhead + 1, NIL, n * sizeof(int));
	memset( in + 1, false, n * sizeof(bool));

	for ( i = 1; i <= n; i++ )
		dp[i] = INF;

	e = 1;
	while ( m-- ) {
	
		scanf("%d%d%d", &u, &v, &t);
		addarc( u, v, t );
	}
}

bool
relax( int u, int v, int dt ) {//SPFA弹性判断

	int		ttmp;

	ttmp = dp[u] + dt;

	if ( ttmp < dp[v] ) {
	
		dp[v] = ttmp;
		return true;
	}

	return false;
}

void
spfa(int end) {//求各点到目标点的最短时间

	int		u, v;
	int		i;

	dp[end] = 0;
	top		= 1;
	stk[1]	= end;
	in[end]	= true;

	while ( top ) {
	
		u 	  = stk[top--];
		in[u] = false;

		for ( i = rhead[u]; i; i = rnext[i] ) {
		
			v = arc[i].u;
			if ( relax( u, v, arc[i].t ) && !in[v] ) {
			
				stk[++top] = v;
				in[v]	   = true;
			}
		}
	}
}

int
astar( int bgn, int end, int k ) {//A*启发式搜索
	//第k次搜索到目标结点表示搜索成功
	//begin,end,k,起始结点,终止结点,和第k短路径

	priority_queue<Node>	heap;

	Node	node;//临时结点
	int		pst;//past time,从bgn到父结点所经历的时间
	int		u;//临时结点的标号
	int		i;//计数变量

	if ( bgn == end )//自己到自己不计,因此需要减去
		//等价就是将k加1
		k++;

	heap.push( Node( bgn, 0, 0 ) );
	while ( !heap.empty() ) {
	
		node = heap.top();
		u	 = node.ith;
		pst  = node.tot;

		if ( u == end && !(--k) )//第k次搜索到终点时便得到答案
			//直接将k短路径的长度返回即可
			return pst;

		heap.pop();

		for ( i = head[u]; i; i = next[i] )
			heap.push( Node( arc[i].v, pst, arc[i].t ) );
	}

	return -1;//有可能除了最短路径之外,从其它点经过时会走到死路
	//比如      1
	//       2  3  4
	//     5    6    7
	//          8
	//5和7都是死路(起始是1,终点是8)
}

int
main() {

	int		n, m;
	int		bgn, end;
	int		k;

	while ( ~scanf("%d%d", &n, &m) ) {
	
		init( n, m );
		scanf("%d%d%d", &bgn, &end, &k);
		spfa(end);
		if ( INF == dp[bgn] ) {//连最短路径都是无穷就意味着
			//bgn到end不可达

			puts("-1");
			continue;
		}
		printf("%d\n", astar( bgn, end, k ));
	}

	return 0;
}

无注释代码:

#pragma G++ optimize("O2")

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define	NIL				0
#define	INF				1000000000

#define	MAXSTATIONN		1001
#define	MAXSIDEWAYN		100001

using namespace std;

struct	Arc {

	int		u;
	int		v;
	int		t;

	Arc(void) {}

	Arc( int xu, int xv, int xt ) :
		u(xu), v(xv), t(xt) {}
};

Arc		arc[MAXSIDEWAYN];
int		e;

int		head[MAXSTATIONN];
int		rhead[MAXSTATIONN];

int		next[MAXSIDEWAYN];
int		rnext[MAXSIDEWAYN];

int		stk[MAXSTATIONN];
bool	in[MAXSTATIONN];
int		top;

int		dp[MAXSTATIONN];

struct	Node {

	int		ith;
	int		tot;
	int		f;

	Node(void) {}

	Node( int xith, int pst, int dt ) :
		ith(xith), tot( pst + dt ),
		f( tot + dp[xith] ) {}

	bool
	operator<(const Node &oth)
	const {
	
		return f > oth.f;
	}
};

void
addarc( int u, int v, int t ) {

	arc[e]   = Arc( u, v, t );

	next[e]	 = head[u];
	head[u]	 = e;

	rnext[e] = rhead[v];
	rhead[v] = e++;
}

void
init( int n, int m ) {

	int		u, v;
	int		t;
	int		i;

	memset( head + 1, NIL, n * sizeof(int));
	memset( rhead + 1, NIL, n * sizeof(int));
	memset( in + 1, false, n * sizeof(bool));

	for ( i = 1; i <= n; i++ )
		dp[i] = INF;

	e = 1;
	while ( m-- ) {
	
		scanf("%d%d%d", &u, &v, &t);
		addarc( u, v, t );
	}
}

bool
relax( int u, int v, int dt ) {

	int		ttmp;

	ttmp = dp[u] + dt;

	if ( ttmp < dp[v] ) {
	
		dp[v] = ttmp;
		return true;
	}

	return false;
}

void
spfa(int end) {

	int		u, v;
	int		i;

	dp[end] = 0;
	top		= 1;
	stk[1]	= end;
	in[end]	= true;

	while ( top ) {
	
		u 	  = stk[top--];
		in[u] = false;

		for ( i = rhead[u]; i; i = rnext[i] ) {
		
			v = arc[i].u;
			if ( relax( u, v, arc[i].t ) && !in[v] ) {
			
				stk[++top] = v;
				in[v]	   = true;
			}
		}
	}
}

int
astar( int bgn, int end, int k ) {

	priority_queue<Node>	heap;

	Node	node;
	int		pst;
	int		u;
	int		i;

	if ( bgn == end )
		k++;

	heap.push( Node( bgn, 0, 0 ) );
	while ( !heap.empty() ) {
	
		node = heap.top();
		u	 = node.ith;
		pst  = node.tot;

		if ( u == end && !(--k) )
			return pst;

		heap.pop();

		for ( i = head[u]; i; i = next[i] )
			heap.push( Node( arc[i].v, pst, arc[i].t ) );
	}

	return -1;
}

int
main() {

	int		n, m;
	int		bgn, end;
	int		k;

	while ( ~scanf("%d%d", &n, &m) ) {
	
		init( n, m );
		scanf("%d%d%d", &bgn, &end, &k);
		spfa(end);
		if ( INF == dp[bgn] ) {

			puts("-1");
			continue;
		}
		printf("%d\n", astar( bgn, end, k ));
	}

	return 0;
}

单词解释:

date:n, 约会

appointment:n, 约定,预约

mandarin:n, 普通话,国语,官话

softly:adv, 温柔的

prince:n, 王子

delta:n, 三角洲

princess:n, 公主

diplomatic:adj, 外交的

mission:n, 使命,任务

erenow:adv, 在此之前

inform:vt, 通知

hall:n, 大厅

commercial:adj, 商业的

via:prep, 通过,经由

enamored:adj, 迷恋的,倾心的

prime minister:n, 首相

muddy:adj, 泥泞的

sideway:n, 人行道,小巷

directed:adj, 定向的

disparate:adj, 不同的,相异的

station:n, 车站,驻地

quote:n, 引用,引号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值