思路: 预处理 每个权值的素因子。问题转化为 以同一个素数作为因子 最长的链,
树形DP求解,ans 由 此点的 最长子链 + 次长子链 相加得到, 然后再更新最长子链
#include<bits/stdc++.h> using namespace std; #define maxn 234567 int pri[maxn+10],n,a[maxn+10]; int x,y,dp[maxn+10][30],id,ans; int head[maxn+10],cnt,sum[maxn]; vector<int>p[maxn+10]; bool isprime[maxn+10],flag; struct node { int v,to; } edge[maxn*2]; void add(int u,int v) { edge[++cnt].v=v; edge[cnt].to=head[u]; head[u]=cnt; } void prime() { isprime[0]=isprime[1]=1; for(int i=2; i<=sqrt(maxn); i++) for(int j=i*i; j<maxn; j+=i) isprime[j]=1; for(int i=2; i<=maxn; i++) if(isprime[i]==0)pri[++id]=i; } void dfs(int u,int fa) { for(int i=head[u]; i!=-1; i=edge[i].to) { int v=edge[i].v; if(v==fa)continue; dfs(v,u); int len1=sum[u]; int len2=sum[v]; for(int j=0; j<len1; j++) for(int k=0; k<len2; k++) if(p[u][j]==p[v][k]) { ans=max(ans,dp[u][j]+dp[v][k]+1); dp[u][j]=max(dp[u][j],dp[v][k]+1); } } } int main() { prime(); memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); if(a[i]==1)continue; else flag=1; for(int j=1; pri[j]<=a[i]&&j<=id; j++) { if(a[i]==1)break; if(a[i]%pri[j]==0) { p[i].push_back(pri[j]); sum[i]++; } while(a[i]%pri[j]==0) a[i]/=pri[j]; if(isprime[a[i]]==0) { p[i].push_back(a[i]); sum[i]++; break; } } } for(int i=1; i<n; i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } if(!flag)printf("0\n"); else { dfs(1,0); printf("%d\n",ans+1); } return 0; }