P4374 [USACO18OPEN]Disruption P
P4374 [USACO18OPEN]Disruption P
分析
还是蛮套路的,我们来总结一下这题的推理过程
首先考虑,从每一条边去找哪一条边是我们需要的最短的替换路。发现太麻烦了,则正难则反,我们从新加的每一条路去考虑。
对于新加的边,其能更新其两个端点在树中的路径
依据此,我们的问题即转化为了,如何快速的对树中路径中的可以替换的最小值进行更新
嗷,还有一个小问题,边权化点权,可以在这里看到操作方法P4114 Qtree1
不难想到利用线段树+树剖
问题就结束了,时间复杂度为
但这依旧不是最优写法,我们可以考虑并查集(最近碰到好几道并查集的,滋,明天看看能不能全部理解一下,欠)
AC_code
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10,INF = 0x3f3f3f3f;
struct Node
{
int l,r,mi;
}tr[N<<2];
int h[N],e[N<<1],ne[N<<1],idx;
int sz[N],dep[N],fa[N],son[N];
int top[N],id[N],ts;
int n,m;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs1(int u,int pa,int depth)
{
sz[u] = 1,dep[u] = depth,fa[u] = pa;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==pa) continue;
dfs1(j,u,depth+1);
if(sz[j]>sz[son[u]]) son[u] = j;
sz[u] += sz[j];
}
}
void dfs2(int u,int tp)
{
top[u] = tp,id[u] = ++ts;
if(!son[u]) return ;
dfs2(son[u],tp);
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==fa[u]||j==son[u]) continue;
dfs2(j,j);
}
}
void pushdown(int u)
{
auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1];
if(root.mi!=INF)
{
left.mi = min(left.mi,root.mi);
right.mi = min(right.mi,root.mi);
root.mi = INF;
}
}
void build(int u,int l,int r)
{
tr[u] = {l,r,INF};
if(l==r) return ;
int mid = l + r >> 1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void modify(int u,int l,int r,int k)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].mi = min(tr[u].mi,k);
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
}
int query(int u,int x)
{
if(tr[u].l==tr[u].r) return tr[u].mi;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(x<=mid) return query(u<<1,x);
else return query(u<<1|1,x);
}
int main()
{
scanf("%d%d",&n,&m);
vector<pair<int,int>> edges;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b;scanf("%d%d",&a,&b);
edges.push_back({a,b});
add(a,b),add(b,a);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
while(top[a]!=top[b])
{
if(dep[top[a]]<dep[top[b]]) swap(a,b);
modify(1,id[top[a]],id[a],c);
a = fa[top[a]];
}
if(a!=b)
{
if(dep[a]<dep[b]) swap(a,b);
modify(1,id[b]+1,id[a],c);
}
}
for(auto edge:edges)
{
int a = edge.first,b = edge.second;
if(dep[a]<dep[b]) swap(a,b);
int res = query(1,id[a]);
if(res==INF) puts("-1");
else printf("%d\n",res);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步