题意:给你一棵树,根节点是1,每个节点都有一个权值,现在要求出每个节点的结果,结果的定义为从根节点到该节
点(包含)路径上所有点的值的gcd,求解每个点时可以把路径上某一个点的值变为0。每个节点的结果独立计算。
思路:可以直接进行dfs,每个节点用set分别保存它到根节点不取每一个点的gcd,比如路径为1 - 2 - 3 - 4,4号节点
保存的set是gcd(a[1], a[2], a[3]), gcd(a[1], a[2], a[4]), gcd(a[1], a[3], a[4]), gcd(a[2], a[3], a[4]), gcd(a[1], a[2], a[3],
a[4]).
这样对于求解每个节点的set我们可以从它的父节点转移过来。
因为约数的值不会很多,很多进行多次gcd后都变成了1.所以并不会T
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
vector<int>g[maxn];
set<int> s[maxn];
set<int>::iterator it;
int n, a[maxn];
void dfs(int u, int pre, int gcd)
{
for(it = s[pre].begin(); it != s[pre].end(); it++)
s[u].insert(__gcd(*it, a[u]));
s[u].insert(gcd);
s[u].insert(__gcd(gcd, a[u]));
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(v == pre) continue;
dfs(v, u, __gcd(gcd, a[u]));
}
}
int main(void)
{
while(cin >> n)
{
for(int i = 0; i < maxn; i++)
g[i].clear(), s[i].clear();
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0, 0);
for(int i = 1; i <= n; i++)
printf("%d%c", *(s[i].rbegin()), i==n ? '\n' : ' ');
}
return 0;
}