题目链接:
题意:给一颗有根数,每个节点都有一个值ai , 求根节点(1)到每个节点路径上的gcd的max , 求每一个节点的时候你可以把路径上的任意一个节点的值ai改为0(只能改一个)或者一个都不改),每个点求max相互独立。
思路: 爆力考虑所有情况 , 实现方法 : 用一个数组记录下每个节点不修改的路径上gcd的max值, 在开一个vector吧路径上修改过的情况的存下来。
注意: 由于一个数的因子个数不会超过 sqrt(n), 所以gcd的max的实际(不重复)的个数不会很多, 所以每次都把vector【节点】的重复的值删掉,可以避免重复考虑。
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
typedef long long ll;
const int maxn = 200005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int n,cnt;
int a[maxn],dp[maxn];
int head[maxn];
vector<int>vec[maxn];
struct node
{
int v,next;
}e[maxn*2];
void add(int u,int v)
{
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int u,int pre)
{
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==pre) continue;
dp[v]=gcd(dp[u],a[v]);
vec[v].push_back(dp[u]);
for(int i=0;i<vec[u].size();i++)
{
vec[v].push_back(gcd(vec[u][i],a[v]));
}
sort(vec[v].begin(),vec[v].end());
vec[v].erase(unique(vec[v].begin(),vec[v].end()),vec[v].end());
dfs(v,u);
}
}
int main()
{
mst(head,-1);
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int x,y;
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dp[1]=a[1];
vec[1].push_back(0);
dfs(1,-1);
for(int i=1;i<=n;i++)
{
dp[i]=max(dp[i],vec[i].back()); //后者取数组里的最大值
}
for(int i=1;i<n;i++)
{
printf("%d ",dp[i]);
}
printf("%d\n",dp[n]);
}