Landmine
Description
给定 \(n\) 个点的树,带边权。每个点有一个半径,从该点能走一步到达半径以内的其他点。对于每个点,询问至少走几步能到达一号点。
Solution
树上邻域问题,考虑建出点分树,维护新的父子关系。对每个点,不断跳父亲,然后查看哪些点能到达,建出反向边,BFS。容易发现能到达的点的距离是一个前缀,考虑用指针维护,已经访问过的点就删去,均摊 O(n\log n)。由于要排序,所以最后是 \(O(n\log^2 n)\)。主要熟悉一下写法,递归的时候注意全局变量的改变是否会产生错误。
以及 hdu 里面关同步流的 cin 读写速度是最快的……
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cassert>
using namespace std;
typedef long long ll;
typedef pair<int,ll> E;
const int N=1e5+7;
int sz[N],ans[N],nd,Fa[N],p[N],dep[N],cur;
ll r[N],D[18][N];
vector<E> g[N],C[N];
bool vis[N];
queue<int> Q;
int count(int u,int f){
int ret=1;
for(E v:g[u])
if(v.first!=f&&!vis[v.first])
ret+=count(v.first,u);
return ret;
}
int Min,s,rt;
void find_rt(int u,int f){
sz[u]=1; int tmp=0;
for(E v:g[u])
if(v.first!=f&&!vis[v.first]){
find_rt(v.first,u);
sz[u]+=sz[v.first],tmp=max(sz[v.first],tmp);
}
tmp=max(s-sz[u],tmp);
if(tmp<Min) Min=tmp,rt=u;
}
void calc_dis(vector<E> &V,int u,int f){
C[rt].push_back(E (u,r[u]-D[cur][u]));
for(E v:g[u])
if(v.first!=f&&!vis[v.first]){
D[cur][v.first]=D[cur][u]+v.second;
calc_dis(V,v.first,u);
}
}
inline bool Cmp(const E &X,const E &Y){return X.second<Y.second;}
void Dfs(int u,int f){
Min=s=count(u,u),rt=u,find_rt(u,u);
Fa[rt]=f,cur=dep[rt]=dep[f]+1;
D[cur][rt]=0,calc_dis(C[rt],rt,rt),vis[rt]=1;
sort(C[rt].begin(),C[rt].end(),Cmp);
int gg=rt;
for(E v:g[gg])
if(!vis[v.first]&&v.first!=f) Dfs(v.first,gg);
}
int main(){
ios::sync_with_stdio(false);
int T; cin>>T;
while(T--){
int n,nd; cin>>n; nd=n;
for(int i=2;i<=n;i++) cin>>r[i];
for(int i=1;i<n;i++){
int u,v; ll dis_;
cin>>u>>v>>dis_;
g[u].push_back(E (v,dis_));
g[v].push_back(E (u,dis_));
}
Dfs(1,0),Q.push(1);
for(int i=1;i<=n;i++)
vis[i]=0,p[i]=C[i].size()-1;
vis[1]=1;
while(!Q.empty()){
int u=Q.front(),y=u; Q.pop();
while(y){
while(~p[y]){
E x=C[y][p[y]];
if(x.second<D[dep[y]][u]) break;
if(!vis[x.first]){
ans[x.first]=ans[u]+1;
Q.push(x.first),vis[x.first]=1;
}
p[y]--;
}
y=Fa[y];
}
}
for(int i=2;i<=n;i++)
printf("%d ",ans[i]? ans[i]:-1);
printf("\n");
for(int i=1;i<=n;i++){
C[i].clear(),g[i].clear();
dep[i]=p[i]=Fa[i]=sz[i]=ans[i]=vis[i]=0;
}
}
}