Codeforces/gym/100685/problem/G Gadget Hackwrench ( LCA )
題目連結:傳送門
題意:
給定一棵有向樹,判斷 U -> V是否可達。
分析:
設dis[u]表示點u到根節點1的距離,val[u]表示點u到根節點1的邊權的和。如果U->V可達那麼U一定可以到達LCA(U,V),LCA(U,V)一定可以到V,我們在建圖的時候按照題目的輸入給定邊的權值設為1,那麼如果U可以到達LCA(U,V),那麼dis[U] - dis[LCA(U,V)] 等於 -(val[U] - val[LCA(U,V)]);dis[V] - dis[LCA(U,V)] 等於val[V]-val[LCA(U,V)]
程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
struct nod{
int to,next,w;
}edge[maxn*2];
int head[maxn],ip,tot;
bool vis[maxn];
int R[maxn*2],ver[maxn*2];
int dp[maxn*2][25];
int first[maxn];
int dis[maxn];
void init(){
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
dis[1]=0,ip=0,tot=0;
}
void add(int u,int v,int w){
edge[ip].to=v;
edge[ip].w=w;
edge[ip].next=head[u];
head[u]=ip++;
}
/***
ver[i]=x:第i個點是x.
first[i]=x: 點i第一次出現的位置是x
R[i]=x:第i個點的深度為x;
dis[i]=x;點i到根節點的距離為x.
***/
void dfs(int u,int dept){
vis[u]=true,ver[++tot]=u,first[u]=tot,R[tot]=dept;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
dis[v]=dis[u]+edge[i].w;
dfs(v,dept+1);
ver[++tot]=u,R[tot]=dept;
}
}
}
int num[maxn];
void dfs2(int u,int pre,int f){
num[u]=f;
for(int i=head[u];i!=-1;i=edge[i].next){
int v= edge[i].to;
if(v==pre) continue;
dfs2(v,u,f+1);
}
}
void ST(int n){
for(int i=1;i<=n;i++) dp[i][0]=i;
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)<=n;j++){
int a = dp[j][i-1],b=dp[j+(1<<(i-1))][i-1];
if(R[a]<R[b]) dp[j][i]=a;
else dp[j][i]=b;
}
}
}
int RMQ(int l,int r){
int k=0;
while(1<<(k+1)<=r-l+1)
k++;
int x = dp[l][k], y=dp[r-(1<<k)+1][k];
if(R[x]<R[y]) return x;
else return y;
}
int LCA(int u,int v){
u=first[u],v=first[v];
if(u>v) swap(u,v);
return ver[RMQ(u,v)];
}
int main()
{
int n,m;
while(~scanf("%d",&n)){
init();
for(int i=0;i<n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v,1);
add(v,u,-1);
}
dfs(1,1);
dfs2(1,0,0);
ST(2*n-1);
scanf("%d",&m);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
int var = LCA(u,v);
if(dis[u]-dis[var]==-(num[u]-num[var])&&dis[v]-dis[var]==(num[v]-num[var]))
puts("Yes");
else
puts("No");
}
}
return 0;
}
相關文章
- 【Lca 倍增】codeforces 832D Misha, Grisha and Underground
- Codeforces Gym 100425H H - Football Bets 構造
- Codeforces Gym 100548F Color (組合數+容斥)
- Codeforces Round #253 (Div. 2) D. Andrey and Problem
- Gym 100543G Virus synthesis 題解
- lca
- Codeforces Round #196 (Div. 2) B. Routine Problem
- codeforces 340CTourist Problem(找規律數學題)
- Codeforces 954I Yet Another String Matching Problem
- codeforces#253 D - Andrey and Problem裡的數學知識
- USB gadget functionfsFunctionNFS
- 求 LCA
- gym建立環境、自定義gym環境
- SDUST OJ Problem G 動態的字串排序字串排序
- Oracle 10g, Export problem through OEM(轉)Oracle 10gExport
- CF741B:https://codeforces.com/problemset/problem/741/BHTTP
- RMQ求lcaMQ
- YTU-OJ-Problem G: 交通工具資訊
- USB gadget configfs
- DFN 序求 LCA
- LCA + 樹上倍增
- LCA(倍增與Tarjan)
- CF1618G Trader Problem 題解
- Problem_2 Majority Problem
- 搭建gym環境
- Codeforces Gym 100286A. Aerodynamics 計算幾何 求二維凸包面積
- LCA學習筆記筆記
- 樹上公共祖先(LCA)
- Codeforces Round 957 (Div 3)(A—G題解)
- linux gadget u盤(Mass storage)Linux
- CodeForces Ruler (1999G1&G2) 題解
- Lca相關演算法演算法
- 淺談倍增法求解LCA
- Mathematical Problem
- 【Python】安裝配置gymPython
- gym序列化、EzPickle類
- codeforces1472G. Moving to the CapitalAPI
- CodeForces 1883G1 Dances (Easy version)