1 条题解
-
0
这里介绍一种只使用了倍增,不需要任何线段树、树链剖分等更高级的技巧的解法。
对于一条替代道路 ,它对且只对 和 的路径上的边产生影响。也就是说,这相当于对于 到 的路径上的所有边 ,设这条边的答案为 ,执行操作 。我们可以把路径拆分为 和 到最近公共祖先的两条路径,然后用倍增维护即可。
#include<bits/stdc++.h> using namespace std; vector<int>G[50505]; int n,m,f[50505][20],g[50505][20],d[50505],ans[50505]; map<pair<int,int>,int>M; void dfs(int u,int p){ d[u]=d[p]+1; for(int v:G[u])if(v!=p)f[v][0]=u,dfs(v,u); } int main(){ cin>>n>>m; for(int i=1,u,v;i<n;i++)cin>>u>>v,G[u].push_back(v),G[v].push_back(u),M[{min(u,v),max(u,v)}]=i; dfs(1,0); for(int i=1;i<16;i++)for(int u=1;u<=n;u++)f[u][i]=f[f[u][i-1]][i-1]; memset(g,0x3f,sizeof g); for(int u,v,w;m--;){ cin>>u>>v>>w; if(d[u]<d[v])swap(u,v); for(int i=15;~i;i--)if(d[f[u][i]]>=d[v])g[u][i]=min(g[u][i],w),u=f[u][i]; for(int i=15;~i;i--)if(f[u][i]!=f[v][i])g[u][i]=min(g[u][i],w),g[v][i]=min(g[v][i],w),u=f[u][i],v=f[v][i]; if(u!=v)g[u][0]=min(g[u][0],w),g[v][0]=min(g[v][0],w); }for(int i=15;i;i--)for(int u=1;u<=n;u++)g[u][i-1]=min(g[u][i-1],g[u][i]),g[f[u][i-1]][i-1]=min(g[f[u][i-1]][i-1],g[u][i]); for(int u=2;u<=n;u++)ans[M[{min(u,f[u][0]),max(u,f[u][0])}]]=g[u][0]; for(int i=1;i<n;i++)cout<<(ans[i]<0x3f3f3f3f?ans[i]:-1)<<'\n'; return 0; }
- 1
信息
- ID
- 6798
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者