CF842C Ilya And The Tree

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

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/108314149