2022-05-05每日刷题打卡
代码源——每日一题
Collision - 题目 - Daimayuan Online Judge
题目描述
siyisss 的王国是由 n 个村镇和 n−1 条双向道路构成的,村镇从 1 到 n 依次编号,每条双向道路连接两个不同的村镇,使得从任意一个村镇出发都可以到达任意一个村镇。接下来请你回答 q 个问题,每次给出两个整数 c, d,表示现在分别有一个人在村镇 c,一个人在村镇 d,现在在 c 的人要用最短的时间到达村镇d,在村镇 d 的人要以最短的时间到达村镇 c,假设两人同时出发,两人的速度也是一样的,每条双向道路的长度也是一样的,请问两人相遇的时候是在某一个村镇,还是在某条双向道路上?
输入描述
第一行输入两个整数 n, q 代表村镇的数量和询问的数量
接下来 n−1 行,每行两个整数用来描述一条双向道路
最后 q,每行两个整数代表 c, d
输出描述
对于每个询问,如果他们在某个村镇相遇,请示出Town,否则输出Road
样例输入1
9 9
2 3
5 6
4 8
8 9
4 5
3 4
1 9
3 7
7 9
2 5
2 6
4 6
2 4
5 8
7 8
3 6
5 6
样例输处1
Town
Road
Town
Town
Town
Town
Road
Road
Road
数据范围
2≤n≤100000
1≤q≤100000
对于每一个询问 1≤ci<di≤n
问题解析
先说结论:当两个点的距离为奇数时,俩人会在路上遇到;当距离为偶数时,俩人会在镇子上遇到。因为俩人同时间走过的长度一样,当两点距离为奇数时,俩人最后会在中间的路上遇到;偶数就会在中间的镇子遇到,很简单的道理。
暴力做法是:我们可以先建图,然后每次询问跑一次bfs,看这个点到另一个点的最短路距离是多少,再根据这个距离的奇偶性来输出结果。但是要是每次都跑一趟肯定会t,能不能优化一下?
(今天比较懒就不一步步来了,直接说终极版本(对我来说是,因为我不会dij等求最短路的,所以我做法很朴实))
为了方便理解做成树的样子(其实和图一样,只是为了方便理解这么画):
然后我们就跑一趟bfs,求出每个点到根节点1的最短距离,把这些存入数组dist里:dist[i]是点i到1的距离。然后我们可以这么看,如果一个点a走到另一个点b且必须经过根节点的话,那么走过的距离就是dist[a]+dist[b],但是我们并不用要经过根节点,我们是要求走过的路最短,所以我们可以省去经过根节点的那段路,即dist[a]和dist[b]中离根节点最近的那段路*2( *2是因为去往根节点在离开根节点这段距离是一样的),(假设是dist[b]离根节点近)那么就变成了:dist[a]+dist[b]-2 *dist[b]==dist[a]-dist[b]。这个就是两个点的最短路距离了,我们只用判断dist[a]-dist[b]的奇偶性即可。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 5e4 + 50;
const int MOD = 1e9 + 7;
inline int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
inline void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 | '0');
}
int main()
{
int n, m, x, y;
n = read(), m = read();
vector<int>dist(n + 1);
unordered_map<int, vector<int>>p;
for (int i = 1; i < n; i++)
{
x = read(), y = read();
p[x].push_back(y);
p[y].push_back(x);
}
queue<int>que;
que.push(1);
int ans = 1;
while (!que.empty())
{
int len = que.size();
for (int i = 0; i < len; i++)
{
int a = que.front();
que.pop();
for (auto i : p[a])
{
if (dist[i] == 0)
{
que.push(i);
dist[i] = ans;
}
}
}
ans++;
}
while (m--)
{
x = read(), y = read();
if ((abs(dist[x] - dist[y])) % 2 == 1)
{
puts("Road");
}
else
{
puts("Town");
}
}
return 0;
}