贪心思想考虑:对于长度大于1的链来说,都要删掉一个节点,这样会更优。
我们发现对于每一个节点,不同的gcd最多存在log200000个,所以记录vis[u][pd][now]表示:遍历完1到u节点,是否有一个点已经删掉,当前gcd为now的状态是否出现过。记忆化搜索。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,u,v;
int ans[N],a[N];
map<int,bool>vis[N][2];
int cnt,head[N];
struct edge{
int next,to;}e[N<<1];
inline void add(int u,int v)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
int gcd(int a,int b)
{
if (!a) return b;
if (a%b==0) return b;
return gcd(b,a%b);
}
void dfs(int u,int fa,int pd,int now)
{
if (vis[u][pd][now]) return;
ans[u]=max(ans[u],now);
vis[u][pd][now]=true;
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa)
{
if (!pd) dfs(e[i].to,u,1,now);
dfs(e[i].to,u,pd,gcd(now,a[e[i].to]));
}
}
int main(){
scanf("%d",&n);
for (register int i=1; i<=n; ++i) scanf("%d",&a[i]);
for (register int i=1; i<n; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs(1,0,0,a[1]);
dfs(1,0,1,0);
for (register int i=1; i<=n; ++i) printf("%d ",ans[i]);
return 0;
}