#A-#D
分析:为简单模拟题。
正误:正确。
#E.Building an Aquarium
分析:一眼二分,求h可行区间最大值。
正误:错误。
反思:右边界取值过大,导致check中间量累加溢出!
#F. Money Trees
分析:用一个数组先计算出个点长度,在对区间长度二分。二分中套双指针算法,还涉及了前缀和。
正误:错误。
反思:只想到了双指针暴力枚举且累加,没有用前缀和!
#G. ABBC or BACB
分析:替换成吃豆子。贪心吃两边。
#H. Mad City
分析:
因为我们有一棵树外加一条边,我们的图正好有一个循环。
如果Marcel和Valeriu共享同一栋建筑,那么答案是“不”。
如果我们从Valeriu的节点进行深度优先搜索,当我们遇到一个已经访问过的节点,而不是当前节点的父节点时,该节点是循环的一部分。此外,这也是Valeriu进入循环的节点。
瓦莱留能永远逃离马塞尔只要他能赶在马塞尔之前到达这个节点。这是因为如果Valeriu处于一个循环中,那么他总是有22可以选择的建筑,他可以在那里奔跑。
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
vector<int> adj[N];
vector<bool> vis(N);
int entry_node = -1;
vector<int> path;
bool dfs1(int u, int p)
{
vis[u] = true;
for(auto v : adj[u])
{
if(v != p && vis[v])
{
entry_node = v;
return true;
}
else if(v != p && !vis[v])
{
if(dfs1(v, u))
{
return true;
}
}
}
return false;
}
int dfs2(int u)
{
vis[u] = true;
int distbruh = N;
for(auto v : adj[u])
{
if(v == entry_node)
{
return 1;
}
if(!vis[v])
{
int dist = dfs2(v)+1;
distbruh = min(dist, distbruh);
}
}
return distbruh;
}
void solve()
{
int n, a, b;
cin >> n >> a >> b;
for(int i = 0; i < n; i++)
{
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs1(b, -1);
vis.assign(n+1, false);
int distMarcel = N, distValeriu = 0;
if(entry_node == a)
{
distMarcel = 0;
}
else
{
distMarcel = dfs2(a);
}
vis.assign(n+1, false);
if(entry_node == b)
{
distValeriu = 0;
}
else
{
distValeriu = dfs2(b);
}
if(distValeriu < distMarcel)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
for(int i = 1; i <= n; i++)
{
adj[i].clear();
vis[i] = false;
}
}
int32_t main(){
int t = 1;
cin >> t;
while (t--) {
solve();
}
}