题目链接<http://10.7.88.2/CLanguage/showproblem?problem_id=2266>
题意:
给出一棵树,和一些额外的边。询问树的每条边,把这条边断开,添加一条额外的边使原图仍然连通。如果存在这样的额外边,输出权值最小的,否则输出-1.
题解:
很容易想到,对于每一条额外边,这一段的简单路上的边都被更新答案,所以就是个树剖裸题。
注意:
- 题目求的是边权值,我把每条边都用下面的点表示,这样两点的lca不能被更新。
- dfs深度过万很可能爆栈,所以要人工写栈。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define ll long long
using namespace std;
const int N=5e4+7;
const int inf=1e9+7;
int n;
int t[N<<2],lz[N<<2],tot;
void bd(int rt,int l,int r){
t[rt]=inf;
if(l==r) return;
int m=l+r>>1;
bd(rt<<1,l,m);
bd(rt<<1|1,m+1,r);
}
void pd(int rt){
if(lz[rt]){
if(t[rt<<1]>t[rt]) t[rt<<1]=lz[rt<<1]=lz[rt];
if(t[rt<<1|1]>t[rt]) t[rt<<1|1]=lz[rt<<1|1]=lz[rt];
lz[rt]=0;
}
}
void upd(int rt,int l,int r,int L,int R,int val){
if(L>R) return;
if(L<=l&&r<=R){
if(t[rt]>val) lz[rt]=t[rt]=val;
return;
}
pd(rt);
int m=l+r>>1;
if(L<=m) upd(rt<<1,l,m,L,R,val);
if(m<R) upd(rt<<1|1,m+1,r,L,R,val);
t[rt]=max(t[rt<<1],t[rt<<1|1]);
}
int que(int rt,int l,int r,int x){
if(l==r) return t[rt];
pd(rt);
int m=l+r>>1;
if(x<=m) return que(rt<<1,l,m,x);
else return que(rt<<1|1,m+1,r,x);
}
struct Edge{
int v,id,nxt;
}e[N*2];
int p[N],edn;
void add(int u,int v,int id){
e[++edn]=(Edge){v,id,p[u]};p[u]=edn;
e[++edn]=(Edge){u,id,p[v]};p[v]=edn;
}
int id[N];
struct Node{
int dt,hs,sz,fa;
int ps,tp;
}a[N];
void dfs(int u){
a[u].dt=a[a[u].fa].dt+1;
a[u].hs=0;
a[u].sz=1;
int mx=0;
for(int i=p[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==a[u].fa) continue;
a[v].fa=u;id[v]=e[i].id;dfs(v);
if(a[v].sz>mx) mx=a[v].sz,a[u].hs=v;
a[u].sz+=a[v].sz;
}
}
void dfs(){
int su[N],si[N],mx[N],top;
for(int i=1;i<=n;i++) si[i]=p[i],mx[i]=0;
su[1]=1; top=1;
a[1].fa=0; a[1].dt=1; a[1].hs=0; a[1].sz=1;
int u,v;
while(1){
u=su[top];
while(~si[u]){
v=e[si[u]].v;
if(a[v].sz) si[u]=e[si[u]].nxt;
else break;
}
if(si[u]==-1){
top--; if(top==0) break;
v=u;u=su[top];
if(a[v].sz>mx[u]) mx[u]=a[v].sz,a[u].hs=v;
a[u].sz+=a[v].sz;
}
else{
a[v].fa=u;id[v]=e[si[u]].id;
a[v].dt=a[u].dt+1;a[v].hs=0;a[v].sz=1;
su[++top]=v;
si[u]=e[si[u]].nxt;
}
}
}
void bdfs(int u,int k){
a[u].tp=k;
a[u].ps=++tot;
if(a[u].hs) bdfs(a[u].hs,k);
for(int i=p[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==a[u].fa||v==a[u].hs) continue;
bdfs(v,v);
}
}
void bdfs(){
int su[N],si[N],top=1;
bool vis[N];
for(int i=1;i<=n;i++) vis[i]=false,si[i]=p[i];
tot=0;
su[1]=1;
a[1].tp=1;a[1].ps=++tot;
int u,v;
while(1){
u=su[top];
if(a[u].hs&&!vis[u]){
v=a[u].hs;
top++;su[top]=v;
a[v].tp=a[u].tp;
a[v].ps=++tot;
vis[u]=true;
continue;
}
while(~si[u]){
v=e[si[u]].v;
if(a[v].ps||v==a[u].hs) si[u]=e[si[u]].nxt;
else break;
}
if(si[u]==-1){
top--; if(top==0) break;
}
else{
top++;su[top]=v;
a[v].tp=v;
a[v].ps=++tot;
}
}
}
void upd(int x,int y,int val){
int xx=a[x].tp,yy=a[y].tp;
while(xx!=yy){
if(a[xx].dt>=a[yy].dt){
upd(1,1,n,a[xx].ps,a[x].ps,val);
x=a[xx].fa;
}
else{
upd(1,1,n,a[yy].ps,a[y].ps,val);
y=a[yy].fa;
}
xx=a[x].tp,yy=a[y].tp;
}
if(a[x].dt<a[y].dt) upd(1,1,n,a[x].ps+1,a[y].ps,val);
else if(a[x].dt>a[y].dt) upd(1,1,n,a[y].ps+1,a[x].ps,val);
}
int pr[N];
int main()
{
int m,u,v,w;
scanf("%d%d",&n,&m);
memset(p,-1,sizeof(p));edn=-1;
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v,i);
}
dfs();
bdfs();
bd(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
upd(u,v,w);
}
for(int i=2;i<=n;i++){
pr[id[i]]=que(1,1,n,a[i].ps);
}
for(int i=1;i<n;i++){
if(pr[i]>=inf) printf("-1\n");
else printf("%d\n",pr[i]);
}
}