P8805 机房
P8805 机房
题意:
任意一点\(u\)的延迟时间 \(t=u的出边数量\)
对于一次询问,求出\(u\)到\(v\)的总延迟时间
思路:
建树vector<int> e[N]
统计每个点的出边数siz[i] = e[i].size()
统计前缀和数组 root->i总共出边数
- u==v 产生延迟siz[u]
- u!=v
- lca(u,v)
- answer=prefix[u]+prefix[v]-2*prefix[lca]+(lca的出边数)
注意:题目“发送方和接收方相同会产生一次延迟”,指的是产生siz[发送方]个时间的延迟,不是1个时间的延迟
图解:
样例1
8 3
2 3
2 4
3 1
3 5
4 6
5 7
5 8
3 6
7 5
1 8
8
4
8

代码:
const int N=1e5+5;
const int K=20;
int n,m;
vector<int> e[N];
int fa[N][21],depth[N];
ll siz[N],pre[N];
void dfs1(int x,int f,ll sz)//sum(root->f)的前缀和
{
fa[x][0]=f;depth[x]=depth[f]+1;
for(int i=1;i<=K;++i){
fa[x][i]=fa[fa[x][i-1]][i-1];
}
pre[x]=sz+siz[x];
for(int v:e[x]){
if(v==f) continue;
dfs1(v,x,pre[x]);
}
}
int LCA(int x,int y)
{
if(depth[x]<depth[y]) swap(x,y);
for(int i=K;i>=0;--i){
if(depth[fa[x][i]]>=depth[y]){
x=fa[x][i];
}
}
if(x==y) return x;
for(int i=K;i>=0;--i){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int main()
{
int x,y,u,v;
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1;i<n;++i){
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
for(int i=1;i<=n;++i){
siz[i]=e[i].size();
}
dfs1(1,0,0);
for(int i=1;i<=m;++i){
cin>>u>>v;
if(u==v) cout<<siz[u]<<"\n";
else{
int lca=LCA(u,v);
cout<<pre[u]+pre[v]-2*pre[lca]+siz[lca]<<"\n";
}
}
return 0;
}

浙公网安备 33010602011771号