这个套路好像是计蒜之道里的一题
考虑枚举gcd
把两端点都是gcd的倍数的边存下来,按照两段点较小值从大到小排序
枚举每一条边,把这条边加入图中,可以用并查集维护出所有联通块的直径,然后就好了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
inline 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++;
}
inline void read(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
int T,n,cnt,G[N],a[N];
struct edge{
int t,nx,w;
}E[N<<1];
inline void addedge(int x,int y,int w){
E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].w=w; G[x]=cnt;
E[++cnt].t=x; E[cnt].nx=G[y]; E[cnt].w=w; G[y]=cnt;
}
vector<pii> ed[N];
ll cst[N];
int dpt[N],dfsl[N],p[N],t;
void dfs(int x,int f){
dpt[x]=dpt[f]+1;
dfsl[++t]=x; p[x]=t;
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f){
cst[E[i].t]=cst[x]+E[i].w;
dfs(E[i].t,x);
dfsl[++t]=x;
}
}
#define Min(x,y) (dpt[x]<dpt[y]?x:y)
int lgt[N],st[N][20];
inline void Pre(){
for(int i=1;i<=t;i++) lgt[i]=lgt[i-1]+((1<<lgt[i-1]+1)==i);
for(int i=1;i<=t;i++) st[i][0]=dfsl[i];
for(int k=1;k<=lgt[t];k++)
for(int i=1;i+(1<<k)-1<=t;i++)
st[i][k]=Min(st[i][k-1],st[i+(1<<k-1)][k-1]);
}
inline int lca(int x,int y){
x=p[x]; y=p[y];
if(x>y) swap(x,y);
int t=lgt[y-x+1];
return Min(st[x][t],st[y-(1<<t)+1][t]);
}
inline ll dist(int x,int y){
return cst[x]+cst[y]-2*cst[lca(x,y)];
}
inline bool cmp(pii x,pii y){
return a[x.fi]<a[y.fi];
}
int fa[N],l[N],r[N];
int getfa(int x){
return x==fa[x]?x:fa[x]=getfa(fa[x]);
}
inline void Merge(int x,int y){
x=getfa(x); y=getfa(y);
if(x==y) return ;
int u=l[x],v=r[x];
#define fix(x,y) if(dist(x,y)>dist(u,v)) u=x,v=y;
fix(l[y],r[y]); fix(l[x],l[y]); fix(l[x],r[y]);
fix(r[x],l[y]); fix(r[x],r[y]);
fa[y]=x; l[x]=u; r[x]=v;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(T);
while(T--){
read(n);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1,x,y,w;i<n;i++){
read(x),read(y),read(w),addedge(x,y,w);
if(a[x]>a[y]) swap(x,y);
for(int j=1;j*j<=a[x];j++)
if(a[x]%j==0){
if(a[y]%j==0)
ed[j].push_back(pii(x,y));
if(a[y]%(a[x]/j)==0)
ed[a[x]/j].push_back(pii(x,y));
}
}
dfs(1,0); Pre();
ll ans=0;
for(int i=1;i<=10000;i++){
if(!ed[i].size()) continue;
sort(ed[i].begin(),ed[i].end(),cmp);
for(int j=0;j<ed[i].size();j++){
fa[ed[i][j].fi]=l[ed[i][j].fi]=r[ed[i][j].fi]=ed[i][j].fi;
fa[ed[i][j].se]=l[ed[i][j].se]=r[ed[i][j].se]=ed[i][j].se;
}
int mn=1<<30; ll mx=0;
for(int j=ed[i].size()-1;~j;j--){
mn=min(mn,a[ed[i][j].fi]);
Merge(ed[i][j].fi,ed[i][j].se);
int u=getfa(ed[i][j].fi);
mx=max(mx,dist(l[u],r[u]));
ans=max(ans,mx*mn*i);
}
ed[i].clear();
}
printf("%lld\n",ans);
for(int i=1;i<=n;i++) G[i]=dpt[i]=cst[i]=0;
t=cnt=0;
}
return 0;
}