Gamers on the Bus

Description
The Programming Team is going to a competition in Miami, Florida. Lior and Sharon decided to drive to the contest separately from the team. Due to a lack of coordination, they have arrived earlier than expected and decided to play a game to pass the time.

The rules are simple: each person takes turns guessing where the bus is. Sharon thinks the playing field is pretty fair because he believes the only knowledge they both have is how much time has passed since the bus left Orlando. But Lior knows better; he packed a map of Florida for the trip and also knows all possible routes between Orlando and Miami! Lior is given another advantage, as he is well-acquainted with the driver of the bus and knows he will arrive in the shortest time possible. Unfortunately, to not raise suspicion that he may be cheating, Lior doesn’t have time to calculate the exact location of the bus, so he needs the help of a fellow programmer to write a program for him.

The Problem:

Given a map of Florida represented as roads and intersections on an x-y plane, help write a program that provides the exact location of the bus given the time elapsed since the bus left Orlando or tells Lior to take his best guess if the answer is ambiguous.

Input
The input begins with a line with a single integer, t, representing the number of trips. Each trip is defined across multiple lines. The first line of each trip begins with two integers, n (2≤n≤105) and m (1≤m≤105), representing the number of intersections and roads, respectively. The following n lines contain two integers, x and y (−1,000≤x≤1,000; −1,000≤y≤1,000), describing the location of the i-th intersection.

This is followed by m lines which each contains two integers, a and b (0≤a<n; 0≤b<n), describing a road between intersections a and b. Orlando is intersection 0, and Miami is intersection n−1. All roads are bidirectional and straight lines (since there are no hills in Florida). It is guaranteed that no roads cross unless they are connected by an intersection.

On the next line of input, an integer, q (1≤q≤105), is given, denoting the number of turns Lior has to make a guess. The following q lines contain a single, non-negative integer, e (e≤1018), which dictates the time elapsed since the bus left Orlando. It’s safe to assume that the bus moves at a pace of one unit per minute (the driver is very safe) and the bus has not arrived in Miami, yet.

Output
For each query on a line by itself, output two numbers, bx and by, separated by a single space, representing the coordinates of the location that Lior should guess to give him the best chance of winning the round given time t. The values should be output rounded to two decimal places (0.024 rounds to 0.02; 0.025 rounds to 0.03). If it is not possible to provide an exact guess, output “Best of Luck” instead.

Samples
Input
1
6 7
0 0
4 0
2 2
0 2
2 0
4 4
0 3
4 0
1 5
2 4
5 2
2 3
1 4
2
2
5
Output
Best of Luck
2.71 2.71

题意
给出一张地图
地图中有n个交叉路口,并且给出每个交叉路口的坐标 x,y;
地图中有m条路,并且给出每条路连接的是那两条交叉口
所有的道路都是双向的

然后公交车从0号交叉口出发,前往n-1号交叉口
每分钟行驶一个单位长度的距离,并且始终按照最短路行驶

给出q次询问,每次给出时间,输出公交车此时的位置
如果不能确定,输出“Best of Luck”!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5;
const double oo = 1e17;
const double eps = 1e-6;

int t, n, m, q, u, v, ptr, sz;

int x[N], y[N], ans[N];
double min_path, pt[2][N];
vector<double> dijkA, dijkB;
vector<pair<ll, int>> qs;
vector<pair<int, double>> adj[N], shortest_paths[N];
priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> paths;
queue<int> build;
bool vis[N];

double pythag(ll dx, ll dy) {
	return sqrt(dx * dx + dy * dy);
}
bool eq(double a, double b) {
	return abs(a - b) < eps;
}
vector<double> dijkstra(int src) {
		vector<double> dist(n, oo);
		dist[src] = 0.0;

		paths.push(make_pair(0.0, src));
		while (paths.size()) {
			pair<double, int> path = paths.top();
			paths.pop();

			if (path.first > dist[path.second])
				continue;

			for (const auto &edge : adj[path.second]) {
				double new_dist = path.first + edge.second;
				if (new_dist < dist[edge.first]) {
					dist[edge.first] = new_dist;
					paths.push(make_pair(new_dist, edge.first));
				}
			}
		}
		
		return dist;
}
int main() {
	cin >> t;
	while (t--) {
		cin >> n >> m;
		for (int i = 0; i < n; ++i)
			cin >> x[i] >> y[i];
		for (int i = 0; i < n; i++)
			adj[i].clear();
		double d;
		for (int i = 0; i < m; ++i) {
			cin >> u >> v;
			d = pythag(abs(x[u] - x[v]), abs(y[u] - y[v]));
			adj[u].push_back(make_pair(v, d));
			adj[v].push_back(make_pair(u, d));
		}
		dijkA = dijkstra(0);
		dijkB = dijkstra(n - 1);
		for (int i = 0; i < n; ++i) {
			shortest_paths[i].clear();
			vis[i] = false;
		}
		vis[0] = true;
		min_path = dijkA[n - 1];
		build.push(0);
		while (build.size()) {
			int node = build.front();
			build.pop();
			
			double from_node = dijkA[node]; 
			for (const auto &edge : adj[node]) {
				v = edge.first;
				double after_edge = dijkB[v];
				if (eq(min_path, from_node + edge.second + after_edge)) {
					shortest_paths[node].push_back(edge);
					if (!vis[v]) {
						build.push(v);
						vis[v] = true;
					}
				}
			}
		}
		cin >> q;
		qs.clear();
		for (int i = 0; i < q; ++i) {
			cin >> u;
			qs.push_back(make_pair(u, i));
		}
		sort(qs.begin(), qs.end());
		ptr = 0;
		paths.push(make_pair(0.0, 0));

		for (int i = 0; i < q; ++i)
			ans[i] = 0;
		for (int i = 0; i < n; ++i)
			vis[i] = false;
		bool from_good_node;
		vis[0] = true;
		while (paths.size()) {
			pair<double, int> path = paths.top();
			paths.pop();

			from_good_node = false;
			if (paths.size() == 0) {
				from_good_node = true;
				while (ptr < q && qs[ptr].first < path.first) {
					if (eq(qs[ptr].first, path.first))
						break;
					ptr++;
				}
				while (ptr < q && eq(qs[ptr].first, path.first)) {
					ans[qs[ptr].second] = 1;
					pt[0][qs[ptr].second] = x[path.second];
					pt[1][qs[ptr].second] = y[path.second];
					ptr++;
				}
			}
			
			for (const auto &edge : shortest_paths[path.second]) {
				if (vis[edge.first])
					continue;
				paths.push(make_pair(dijkA[edge.first], edge.first));
				vis[edge.first] = true;
			}
			if (from_good_node && paths.size() == 1) {
				pair<double, int> edge = paths.top();

				while (ptr < q && qs[ptr].first < edge.first) {
					ans[qs[ptr].second] = 1;

					double traverse = qs[ptr].first - path.first;

					double dx = x[edge.second] - x[path.second];
					double dy = y[edge.second] - y[path.second];
					double mag = edge.first - path.first;
					dx /= mag;
					dy /= mag;

					pt[0][qs[ptr].second] = x[path.second] + dx * traverse;
					pt[1][qs[ptr].second] = y[path.second] + dy * traverse;
					ptr++;
				}
			}
		}
		
		for (int i = 0; i < q; ++i) {
			if (ans[i]) printf("%.2f %.2f\n", pt[0][i], pt[1][i]); 
			else printf("Best of Luck\n");
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值