c++ - Codeforces 关于二进制提升和 LCA 的问题
问题描述
最近,我在 Codeforces 上解决了这个问题,但我没有通过测试用例。我看不到测试用例,也看不到其他人的解决方案,因为这是一道道馆题。因为,我无法查看我的代码失败的测试用例,所以我需要一些帮助。我保证代码非常易读。问题主要是关于二进制提升和 LCA 计算。
可能知道,树懒生活在树上。因此,大卫有一只宠物树懒,当他解决编程问题时,他让它在他未加权的树上玩耍。有时,大卫会注意到他的树懒位于树中的特定节点上,并要求它移动到其他节点。
当然,树懒是出于善意,但可惜它只有足够的能量在大多数边缘移动。如果树懒需要穿过少于边缘才能到达节点,它会到达那里然后打个盹。否则,它会在退休前尽可能接近并闲置等待进一步消化。
树懒最终会去哪里?此外,由于这种情况经常发生,大卫希望您回答查询,每一个都类似的形式。
输入
第一行将包含一个整数,即树中的节点数。以下 -1 行将包含两个整数 和 ,描述树中的边。这些边将形成一棵树。
之后,将有一行包含一个整数 ,即大卫激励他的树懒移动的次数。接下来的行,每行包含三个整数 、 和 :树懒开始的节点,大卫要求树懒移动到的节点,以及树懒开始时的能量。
int LOGN = 19;
int n;
int timer = 0;
vector<int> adj[300005];
bool vis[300005];
int p[300005], tin[300005], tout[300005];
vector<int> d(300005,0);
int dp[300005][20];
void dfs(int v, int parent)
{
tin[v] = ++timer;
if (parent != -1)
d[v] = d[parent] + 1;
p[v] = parent;
dp[v][0] = parent;
for (int i = 1; i < LOGN; i++){
if (dp[v][i — 1] == -1)
dp[v][i] = -1;
else
dp[v][i] = dp[dp[v][i — 1]][i — 1];
}
for (auto u : adj[v]){
if (u != parent)
dfs(u, v);
}
tout[v] = ++timer;
}
bool isAncestor(int p, int c){ // check if p is ancestor of c
return (tin[p] <= tin[c] && tout[p] >= tout[c]);
}
int lift(int v, int steps) //find the y-th ancestor of x
{
for (int i = 0; i < 19; ++i){
if ((1 << i) & steps){
v = dp[v][i];
if (v == -1)
return -1;
steps -= (1 << i);
}
}
return v;
}
int LCA(int u, int v)
{
if (isAncestor(u, v))
return u;
if (isAncestor(v, u))
return v;
for (int i = 18; i >= 0; i--)
{
if (dp[u][i] == -1)// -1 should not be passed
continue;
if (!isAncestor(dp[u][i], v))
u = dp[u][i];
}
return dp[u][0];
}
void solve()
{
cin>>n;
timer=0;
for(int i=0;i<n-1;i++){// Input
int x,y;
cin>>x>>y;
x--;y--;
adj[x].pb(y);
adj[y].pb(x);
}
dfs(0,-1);
tout[0]=++timer;
int q;
cin>>q;
for(int z=0;z<q;z++){
int u,v,energy;
cin>>u>>v>>energy;
u--;v--;
if(isAncestor(u,v))// u is ancestor of v
{
if(d[v]-d[u]<=energy)// reachable
cout<<v+1<<endl;
else{// midway: lift
int res=lift(v,energy);
cout<<res+1<<endl;
}
}
else if(isAncestor(v,u))// v is ancestor of u
{
if(d[u]-d[v]<=energy)// reachable
cout<<v+1<<endl;
else{/// midway: lift
int res=lift(u,d[u]-d[v]-energy);
cout<<res+1<<endl;
}
}
else{
int lca=LCA(u,v);
int dist=d[u]+d[v]-2*d[lca];
if(energy>=dist)
cout<<v+1<<endl;
else{
// find vertex of the path from u to v with distance of energy from u
int dist1=d[u]-d[lca];
int dist2=d[v]-d[lca];
// lies on the path from u to LCA
if(energy<=dist1){
int res=lift(u,energy)+1;
cout<<res<<endl;
}
// lies on the path from LCA to v
else{
int rem=energy-dist1;
dist2-=rem;
int res=lift(v,dist2)+1;
cout<<res<<endl;
}
}
}
}
}
signed main()
{
FAST;
solve();
return 0;
}
解决方案
推荐阅读
- java - Spring Security Crypto - BadPaddingException:给定最终块未正确填充。如果在解密期间使用了错误的密钥,则可能会出现此类问题
- ios - 如何在 iOS 中的领域数据库上实现多个用户?
- c++ - 当我使用“向量”或其他动态数组时,程序在开始时闪回
- terraform - Terraform,计数时列出错误的字符串
- asp.net - 什么会导致 VB.NET DLL 在被可执行代码调用时运行良好时在 IIS 中失败?
- postgresql - 加快 Postgresql 行计数
- python - 尝试从破解python中的编码面试中的urlify问题编写java代码
- angular - 在 Angular Material 步进器中跳过步骤(取决于某些条件)
- c - 重新打开标准输入 EOFerror
- matlab - MATLAB 精度在处理浮点数时导致问题