先枚举
gcd
g
c
d
,把所有边找出来,按照权值小的端点排序,然后从大到小枚举边,并查集维护直径就好了。
时间复杂度
O(nAi−−√(logn+α))
O
(
n
A
i
(
log
n
+
α
)
)
。
#include<bits/stdc++.h>
using namespace std;
char nc() {
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
void Read(int& x) {
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
typedef long long ll;
const int N=200010;
const int M=18;
int k,n,m,x,y,z,T;
int cnt,cur,mx;
int a[N];
int u[N],v[N];
int f[N],A[N],B[N],lst[N];
int nx[N],t[N],w[N],h[N],num;
int pos[N],lg2[N];
ll dis[N];
ll Ans,Res,d[N],c[N],st[N][M],ed[N][M];
vector<int>g[10010];
void Add(int x,int y,int z) {
t[++num]=y;w[num]=z;nx[num]=h[x];h[x]=num;
}
int Gcd(int x,int y) {
return !y?x:Gcd(y,x%y);
}
void Update(int x,int y) {
for(int i=1;i*i<=x;i++)
if(!(x%i)) {
g[i].push_back(y);
if(i*i!=x) g[x/i].push_back(y);
}
}
void Dfs(int x,int y) {
c[++cnt]=d[x];pos[x]=cnt;
for(int i=h[x];i;i=nx[i])
if(t[i]!=y) {
d[t[i]]=d[x]+w[i];
Dfs(t[i],x);
c[++cnt]=d[x];
}
}
void init() {
cnt=0;
Dfs(1,0);
for(int i=2;i<=cnt;i++) lg2[i]=lg2[i>>1]+1;
for(int i=1;i<=cnt;i++) st[i][0]=ed[i][0]=c[i];
for(int j=1;j<M;j++)
for(int i=1;i<=cnt;i++) {
int t=1<<j-1;
if(i+(t<<1)-1<=cnt) st[i][j]=min(st[i][j-1],st[i+t][j-1]);
if(i-(t<<1)>=0) ed[i][j]=min(ed[i][j-1],ed[i-t][j-1]);
}
}
ll Query(int l,int r) {
l=pos[l];r=pos[r];
if(l>r) swap(l,r);
int k=lg2[r-l+1];
return min(st[l][k],ed[r][k])<<1;
}
bool Cmp(int x,int y) {
return a[u[x]]>a[u[y]];
}
int Find(int x) {
return f[x]==x?x:f[x]=Find(f[x]);
}
void Un(int x,int y) {
if(lst[x]!=cur) lst[x]=cur,f[x]=A[x]=B[x]=x,dis[x]=0;
if(lst[y]!=cur) lst[y]=cur,f[y]=A[y]=B[y]=y,dis[y]=0;
x=Find(x);y=Find(y);
f[y]=x;
int a1=A[x],b1=B[x];
if(dis[y]>dis[x]) dis[x]=dis[y],a1=A[y],b1=B[y];
ll t=d[A[x]]+d[A[y]]-Query(A[x],A[y]);
if(t>dis[x]) dis[x]=t,a1=A[x],b1=A[y];
t=d[A[x]]+d[B[y]]-Query(A[x],B[y]);
if(t>dis[x]) dis[x]=t,a1=A[x],b1=B[y];
t=d[B[x]]+d[A[y]]-Query(B[x],A[y]);
if(t>dis[x]) dis[x]=t,a1=B[x],b1=A[y];
t=d[B[x]]+d[B[y]]-Query(B[x],B[y]);
if(t>dis[x]) dis[x]=t,a1=B[x],b1=B[y];
A[x]=a1;B[x]=b1;
Res=max(Res,dis[x]);
}
void Solve(int id) {
sort(g[id].begin(),g[id].end(),Cmp);
++cur;Res=0;
for(int i=0;i<g[id].size();i++) {
int x=g[id][i];
Un(u[x],v[x]);
Ans=max(Ans,Res*id*a[u[x]]);
}
}
int main() {
Read(T);
while(T--) {
Read(n);
mx=0;
for(int i=1;i<=n;i++) Read(a[i]),h[i]=0,mx=max(mx,a[i]);
for(int i=1;i<=mx;i++) g[i].clear();
num=0;
for(int i=1;i<n;i++) {
Read(x),Read(y),Read(z),Add(x,y,z),Add(y,x,z),u[i]=x,v[i]=y;
if(a[u[i]]>a[v[i]]) swap(u[i],v[i]);
Update(Gcd(a[u[i]],a[v[i]]),i);
}
init();
Ans=0;
for(int i=1;i<=mx;i++) Solve(i);
printf("%lld\n",Ans);
}
return 0;
}