贪心思想考虑:对于长度大于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; }