C. Ilya And The Tree
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Ilya is very fond of graphs, especially trees. During his last trip to the forest Ilya found a very interesting tree rooted at vertex 1. There is an integer number written on each vertex of the tree; the number written on vertex i is equal to ai.
Ilya believes that the beauty of the vertex x is the greatest common divisor of all numbers written on the vertices on the path from the root to x, including this vertex itself. In addition, Ilya can change the number in one arbitrary vertex to 0 or leave all vertices unchanged. Now for each vertex Ilya wants to know the maximum possible beauty it can have.
For each vertex the answer must be considered independently.
The beauty of the root equals to number written on it.
Input
First line contains one integer number n — the number of vertices in tree (1 ≤ n ≤ 2·105).
Next line contains n integer numbers ai (1 ≤ i ≤ n, 1 ≤ ai ≤ 2·105).
Each of next n - 1 lines contains two integer numbers x and y (1 ≤ x, y ≤ n, x ≠ y), which means that there is an edge (x, y) in the tree.
Output
Output n numbers separated by spaces, where i-th number equals to maximum possible beauty of vertex i.
Examples
input
2
6 2
1 2
output
6 6
input
3
6 2 3
1 2
1 3
output
6 6 6
input
1
10
output
10
题目大意
有一棵根节点为1的树,每个结点都有权值。求每个结点从根节点到它的路径上的点的最大gcd(最多把一个路径上的一个点权值变成0)。
解题思路
由于一个数的因子个数为松散的
n‾‾√
,而且一条路径上的gcd会很快的将到1。所以如果我们从根节点往下dfs,记录所有可以通过把1个或0个点权值变成0得到的gcd。对于每个点,答案就是转移到当前点的所有gcd的最大值。
时间复杂度为
O(V∗d)
,其中
V
为顶点数,
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <ctime>
#include <bitset>
using namespace std;
#define INF 0x3f3f3f3f
#define ULL unsigned long long
#define LL long long
#define fi first
#define se second
#define mem(a, b) memset((a),(b),sizeof(a))
#define sqr(x) ((x)*(x))
const int MAXV=500000+3;
int V, a[MAXV];
vector<int> G[MAXV];//图的邻接矩阵表示
int path[MAXV];//从根节点到当前结点路径的gcd
vector<int> dp[MAXV];//从根节点到当前结点所有可以得到的gcd
void dfs(int u, int fa)
{
if(~fa)//非根节点
{
path[u]=__gcd(path[fa], a[u]);
dp[u].push_back(path[fa]);//把当前结点的权值变成0
for(int i=0;i<dp[fa].size();++i)
dp[u].push_back(__gcd(dp[fa][i], a[u]));
sort(dp[u].begin(), dp[u].end());
dp[u].erase(unique(dp[u].begin(), dp[u].end()), dp[u].end());//去重
}
else//根节点
{
path[u]=a[u];
dp[u].push_back(0);
dp[u].push_back(a[u]);
}
for(int i=0;i<G[u].size();++i)
if(G[u][i]!=fa)
dfs(G[u][i], u);
}
int main()
{
scanf("%d", &V);
for(int i=1;i<=V;++i)
scanf("%d", &a[i]);
for(int i=1;i<V;++i)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, -1);
for(int i=1;i<=V;++i)
printf("%d%c", dp[i].back(), i==V?'\n':' ');
return 0;
}