分析
删边是很难的,
所以我们反过来,从后往前加边。
我们知道树的直径有一个性质,
当两个树合并的时候,
新树的直径的两个端点一定是原来两棵树的四个端点中的两个。
证明比较简单。
我们就先在原树上面预处理倍增数组,
对于每棵树,我们记录它直径的长度,以及两个端点。
合并的时候就用四个端点两两之间跑lca。
code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 200003
#define db double
#define P putchar
#define G getchar
#define mo 1000000007
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=G();
n*=w;
}
void write(ll x)
{
if(x>9) write(x/10);
P(x%10+'0');
}
int v[N],next[N*2],a[N*2],b[N],tot;
int n,p[N],x,y,q[N][2],t;
int gf[N],f[N][18],g[N][18];
int deep[N],l[N],r[N],len[N],tl,tr;
ll ans,s[N];
void ins(int x,int y)
{
next[++tot]=b[x];
a[tot]=y;
b[x]=tot;
}
void bfs()
{
int d[N],x=0,y=1;
bool bz[N];
memset(bz,1,sizeof(bz));
bz[d[1]=1]=0;
while(x<y)
{
x++;
for(int i=b[d[x]];i;i=next[i])
if(bz[a[i]])
{
bz[a[i]]=0;
deep[a[i]]=deep[d[x]]+1;
f[a[i]][0]=d[x];
g[a[i]][0]=v[a[i]];
d[++y]=a[i];
}
}
}
int get(int x)
{
if(gf[x]!=x)gf[x]=get(gf[x]);
return gf[x];
}
ll ksm(ll x,int y)
{
ll s=1;
while(y)
{
if(y%2)s=s*x%mo;
x=x*x%mo;
y=y>>1;
}
return s;
}
int lca(int x,int y)
{
int s=0;
if(deep[y]>deep[x])swap(x,y);
for(int i=16;i>=0;i--)
if(deep[f[x][i]]>=deep[y])s+=g[x][i],x=f[x][i];
if(x==y)return s+v[x];
for(int i=16;i>=0;i--)
if(f[x][i]!=f[y][i])s+=g[x][i]+g[y][i],x=f[x][i],y=f[y][i];
s+=g[x][0]+g[y][0];
return s+v[f[x][0]];
}
int main()
{
read(n);ans=1;
for(int i=1;i<=n;i++)
read(v[i]),l[i]=r[i]=gf[i]=i,ans=ans*v[i]%mo,len[i]=v[i];
tot=0;s[n]=ans;
for(int i=1;i<n;i++)
read(x),read(y),ins(x,y),ins(y,x),q[i][0]=x,q[i][1]=y;
deep[1]=1;
bfs();
for(int j=1;j<17;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
for(int i=1;i<n;i++)
read(p[i]);
for(int k=n-1;k;k--)
{
x=q[p[k]][0];
y=q[p[k]][1];
x=get(x);
y=get(y);
ans=ans*ksm(len[x],mo-2)%mo*ksm(len[y],mo-2)%mo;
tl=l[x];tr=r[x];
if(len[x]<len[y])len[x]=len[y],tl=l[y],tr=r[y];
t=lca(l[x],r[y]);
if(t>len[x])len[x]=t,tl=l[x],tr=r[y];
t=lca(l[x],l[y]);
if(t>len[x])len[x]=t,tl=l[x],tr=l[y];
t=lca(l[y],r[x]);
if(t>len[x])len[x]=t,tl=l[y],tr=r[x];
t=lca(r[x],r[y]);
if(t>len[x])len[x]=t,tl=r[x],tr=r[y];
l[x]=tl;r[x]=tr;
gf[y]=x;
ans=ans*len[x]%mo;
s[k]=ans;
}
for(int i=1;i<=n;i++)
write(s[i]),P('\n');
}