ural 2034. Caravans

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2034


题意描述:一个劫镖游戏共有N个城镇,M条长度为1双向边,保证连通;镖车从s点押镖到f点,有一波山贼居住在r点,早已获悉镖车路径的他们准备当镖车行进到某点时,从r点疾行,闪现劫镖;限制如下:谨慎镖车仅走最短路,傲娇山贼仅会攻击镖车路线节点中离r点最近的点;问题是求出在众多最短路当中,山贼们可能需要到达点的最大距离;


思路大致是两遍BFS,首先找出所有点到d点的最短距离,然后找出所有点到f点的最短距离;从s点出发,顺着到f点距离递减的各个方向,更新各条路线到d的动态最短距离,和各点所属路径中当前与d的最大距离;终点f处出最终结果;


AC代码:

//#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))

struct Node{
	int dlen, flen, line;    // 依次为:到贼窝d的距离、到终点f的距离、所有经过该点路径中到贼窝距离的最大值
	bool visit;
	Node() :dlen(-1), flen(-1), line(-1), visit(false){}
};

const int maxn = 1e5 + 10;
vector<int>table[maxn];	// 记录邻接信息
vector<Node>v(maxn);
int s, f, d, n, m;



void BFS(){

	queue<int>q;
	v[d].dlen = 0;
	q.push(d);

	while (!q.empty()){    // 求出所有点到贼窝d的距离
		int src = q.front(); q.pop();
		for (int tar : table[src])
		if (v[tar].dlen == -1){
			v[tar].dlen = v[src].dlen + 1;
			q.push(tar);
		}
	}

	v[f].flen = 0;
	q.push(f);
	while (!q.empty()){    //求出所有点到终点f的距离
		int src = q.front(); q.pop();
		for (int tar : table[src])
		if (v[tar].flen == -1){
			v[tar].flen = v[src].flen + 1;
			q.push(tar);
		}
	}

	v[s].line = v[s].dlen;
	q.push(s);
	while (!q.empty()){  //从起点处,按照各个到终点距离递减的方向,更新路径最短距离line,以及经过各店路径最短距离的最大值
		int src = q.front(); q.pop();
		v[src].visit = true;
		for (int tar : table[src]){
			if (v[tar].flen != v[src].flen - 1)continue;
			v[tar].line = max(v[tar].line, v[src].line); // 求过该点所有路径中最大line值
			v[tar].line = min(v[tar].line, v[tar].dlen); //用该点到贼窝距离更新line值
			if (v[tar].visit == false){
				q.push(tar);
				v[tar].visit = true;
			}
		}
	}

	printf("%d\n", v[f].line);

}


void func(){
	scanf("%d%d", &n, &m);

	while (m--){
		int src, tar;
		scanf("%d%d", &src, &tar);
		table[src].push_back(tar);
		table[tar].push_back(src);
	}

	scanf("%d%d%d", &s, &f, &d);
	BFS();
}

int main(){

	//freopen("out.txt", "w", stdout);
	//freopen("in.txt", "r", stdin);

	func();

}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值