This way

## Title:

I will give you a graph with n points and m edges. I will ask you the maximum value (< 1e9) that each edge can be replaced, so that it can be in the minimum spanning tree after replacement.

## Explanation:

These are what immortal practice, and their code length is also short, more importantly, baidu I can not find.
Then my weak chicken can only think of tree chain segmentation, and the code is long.
First, the edge is divided into the case that it is on the tree and the case that it is not on the tree. First of all, it is good to consider the case that it is not on the tree, and it must be replaced with the maximum value on the path of two nodes.
In the case of trees, if this edge is removed, then it is to select the shortest edge from its subtree to connect to the points other than its subtree. If dfs is hard to do, because it is not easy to maintain the edge coming from below, then it is found that there is a range of the edge under its reality, that is, the path between the two points.
But notice that we need to change the save edge to save point, that is to say, we need to change the edge right to point right and save it to the son node. Then we need to find out the lca of two points, and then divide it into two line segments to store. The same is true for query.
The code is extremely long, no wonder only such a few people do it.

```#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<int,int>
const int N=1e6+5;
struct node
{
int to,next;
}e[N*2];
int f_mx[N*4],mx[N*4],mi[N*4],f_mi[N*4];
int n,m,rt;
void add(int x,int y)
{
e[cnt].to=y;
}
void dfs1(int u)
{
siz[u]=1;
{
int v=e[i].to;
if (v!=fa[u][0])
{
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if (son[u]==0||siz[v]>siz[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int f)
{
tim++;
top[u]=f;
pos[u]=tim;
if (son[u]) dfs2(son[u],f);
{
int v=e[i].to;
if (v!=fa[u][0]&&v!=son[u])
{
dfs2(v,v);
}
}
en[u]=tim;
}
void pushdown(int root)
{
mx[root<<1]=max(mx[root<<1],f_mx[root]);
mx[root<<1|1]=max(mx[root<<1|1],f_mx[root]);
f_mx[root<<1]=max(f_mx[root<<1],f_mx[root]);
f_mx[root<<1|1]=max(f_mx[root<<1|1],f_mx[root]);
f_mx[root]=0;
mi[root<<1]=min(mi[root<<1],f_mi[root]);
mi[root<<1|1]=min(mi[root<<1|1],f_mi[root]);
f_mi[root<<1]=min(f_mi[root<<1],f_mi[root]);
f_mi[root<<1|1]=min(f_mi[root<<1|1],f_mi[root]);
f_mi[root]=1e9;
}
void add(int l,int r,int root,int ql,int qr,int val,int op)
{
if(l>=ql&&r<=qr)
{
if(op){
mx[root]=max(mx[root],val);
f_mx[root]=max(f_mx[root],val);
}
else{
mi[root]=min(mi[root],val);
f_mi[root]=min(f_mi[root],val);
}
return ;
}
pushdown(root);
int mid=l+r>>1;
if(mid>=ql)
if(mid<qr)
mx[root]=max(mx[root<<1],mx[root<<1|1]);
mi[root]=min(mi[root<<1],mi[root<<1|1]);
}
int q_mx(int l,int r,int root,int ql,int qr)
{
if(l>=ql&&r<=qr)
return mx[root];
int mid=l+r>>1;
pushdown(root);
int ans=0;
if(mid>=ql)
ans=q_mx(l,mid,root<<1,ql,qr);
if(mid<qr)
ans=max(ans,q_mx(mid+1,r,root<<1|1,ql,qr));
return ans;
}
int q_mi(int l,int r,int root,int p){
if(l==r)
return mi[root];
int mid=l+r>>1;
pushdown(root);
if(mid>=p)
return q_mi(l,mid,root<<1,p);
else
return q_mi(mid+1,r,root<<1|1,p);
}
void update(int x,int y,int val,int op)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]][0];
}
if (pos[x]>pos[y]) swap(x,y);
}
int query(int x,int y)
{
int ans=0;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,q_mx(1,n,1,pos[top[x]],pos[x]));
x=fa[top[x]][0];
}
if (pos[x]>pos[y]) swap(x,y);
ans=max(ans,q_mx(1,n,1,pos[x],pos[y]));
return ans;
}
struct edge{
int x,y,v,id;
bool operator<(const edge& a)const
{
return v<a.v;
}
}p[N];
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)return x;
for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int f[N],in[N];
int finds(int x){return x==f[x]?f[x]:f[x]=finds(f[x]);}
void deal(){
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int ans[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=m;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].v),p[i].id=i;
dep[1]=1;
sort(p+1,p+1+m);
for(int i=1;i<=m;i++){
int fax=finds(p[i].x);
int fay=finds(p[i].y);
if(fax!=fay){
in[p[i].id]=1;
f[fay]=fax;
}
}
dfs1(1);
dfs2(1,1);
deal();
for(int i=1;i<=n*4;i++)
mi[i]=f_mi[i]=1e9;
for(int i=1;i<=m;i++){//Update according to circumstances. If the maximum value is updated on the tree, the minimum value is updated if not on the tree
int x=p[i].x,y=p[i].y,firstson,val=p[i].v;
int l=lca(x,y);
if(y!=l)
{
firstson=y;
for(int i=20;i>=0;i--)
if(dep[fa[firstson][i]]>dep[l])
firstson=fa[firstson][i];
update(firstson,y,val,in[p[i].id]?1:0);
}
if(x!=l)
{
firstson=x;
for(int i=20;i>=0;i--)
if(dep[fa[firstson][i]]>dep[l])
firstson=fa[firstson][i];
update(firstson,x,val,in[p[i].id]?1:0);
}
}
for(int i=1;i<=m;i++){
if(in[p[i].id])//If the minimum value of the child node is queried on the tree
ans[p[i].id]=q_mi(1,n,1,dep[p[i].x]>dep[p[i].y]?pos[p[i].x]:pos[p[i].y]);
else{//Otherwise, query the maximum value
int x=p[i].x,y=p[i].y,firstson,val=p[i].v;
int l=lca(x,y);
int aa=0;
if(y!=l)
{
firstson=y;
for(int i=20;i>=0;i--)
if(dep[fa[firstson][i]]>dep[l])
firstson=fa[firstson][i];
aa=query(firstson,y);
}
if(x!=l)
{
firstson=x;
for(int i=20;i>=0;i--)
if(dep[fa[firstson][i]]>dep[l])
firstson=fa[firstson][i];
aa=max(aa,query(firstson,x));
}
ans[p[i].id]=aa;
}
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}

```
City of heaven 542 original articles published, praised 31, visited 50000+ His message board follow