这里主要是了解一下套路,首先说一下树的直径的性质。
1.任何一个点到它所在的联通块中距离最远的点一定是树的直径两点之一。
2.两个连通块合并以后,新的树的直径一定为原先两个连通块中树的直径中的两个。
了解完这个,我们来看这道题,根据树的直径的性质,我们可以来维护连通块,那一个难点就是删边很难处理,但它是离线操作,我们就可以考虑时光倒流,倒着处理,把删边改为加边。
维护连通性,我们就可以用并查集,然后再不断合并即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+10;
int n,m;
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
int fa[N],s[N][2];
struct lmy
{
int x,y,z;
}e[N];
int h[N],nxt[N<<1],to[N<<1],w[N<<1],tot;
void add(int x,int y,int dt)
{
to[++tot]=y;
nxt[tot]=h[x];
w[tot]=dt;
h[x]=tot;
}
int f[N][25],dep[N],dis[N];
void dfs(int u,int fat)
{
dep[u]=dep[fat]+1,f[u][0]=fat;
for(int i=1;i<24;++i) f[u][i]=f[f[u][i-1]][i-1];
for(int i=h[u];i;i=nxt[i])
{
int v=to[i];
if(v==fat) continue;
dis[v]=dis[u]+w[i];
dfs(v,u);
}
return ;
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=23;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(int i=23;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
int get(int a,int b){return dis[a]+dis[b]-2*dis[lca(a,b)];}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int ans[N],nowmax;
int Mx[N];
void merge(int x,int y)
{
fa[y]=x;
int maxx=0;
int now[10]={s[x][0],s[x][1],s[y][0],s[y][1]};
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
int nowx=now[i],nowy=now[j];
int dis=get(nowx,nowy);
if(dis>maxx)
{
maxx=dis,s[x][0]=nowx,s[x][1]=nowy;
Mx[x]=dis;
}
}
}
nowmax=max(nowmax,Mx[x]);
return ;
}
int d[N],vis[N];
void solve()
{
n=read(),m=read(),tot=0,nowmax=0;
for(int i=1;i<=n;i++)
{
fa[i]=i,s[i][0]=s[i][1]=i;
h[i]=dep[i]=dis[i]=0;
ans[i]=0,Mx[i]=0;
for(int j=0;j<=24;++j) f[i][j]=0;
vis[i]=0;
}
for(int i=1;i<=n-1;i++)
{
int a=read(),b=read(),dt=read();
add(a,b,dt),add(b,a,dt);
e[i]={a,b,dt};
}
dfs(1,0);
for(int i=1;i<=m;++i) d[i]=read(),vis[d[i]]=1;
for(int i=1;i<n;++i)
{
if(vis[i]) continue;
int x=e[i].x,y=e[i].y;
if(dep[x]>dep[y]) swap(x,y);
merge(find(x),find(y));
}
for(int i=m;i>=1;i--)
{
int x=e[d[i]].x,y=e[d[i]].y;
if(dep[x]>dep[y]) swap(x,y);
ans[i]=nowmax;
merge(find(x),find(y));
}
for(int i=1;i<=m;++i) cout<<ans[i]<<"\n";
return ;
}
signed main()
{
int t=read();
while(t--)
{
solve();
}
return 0;
}