Codeforces 842C - Ilya And The Tree - 树形DP或DFS

链接:

  http://codeforces.com/contest/842/problem/C


题目:

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


题意:

  给你一颗具有n个节点的树,节点i的权值为 ai ,然后有 n1 条边,然后让你输出从节点1出发到每个节点(包括节点1本身)的最大公共 gcd ,这里有一个特殊操作,就是你可以把某一个节点的权变为0,这个特殊操作对于每个点的询问是独立的。

  特别的,规定根节点的gcd等于根节点的权,此外,规定对于任意正整数 a ,都有 gcd(a,0)=a


思路:

  我采用的是DFS的写法,每次记录下当前节点,它的父亲,当前节点的深度,和到当前节点的父节点为止没有进行过特殊操作的gcd,然后用一个数组v去记录某个因数的出现次数,ans用来离线答案。

  对于每个节点,如果他的某个因子的出现次数大于等于他的深度,那么这个因子一定是从根到这个点的路劲上的一个公共gcd,和ans取一下max,dfs完叶节点回溯之前在把这个数的所有因子从v集合里去掉就可以。


实现:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define read read()
#define edl putchar('\n')
#define ll long long
#define clr(a,b) memset(a,b,sizeof a)
#define rep(i,m,n) for(int i=m ; i<=n ; i++)
inline int read{ int x=0;char c=getchar();while(c<'0' || c>'9')c=getchar();while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); }return x;}
using namespace std;
int gcd(int p, int q) {return q==0?p:gcd(q,p%q);}
const int maxn = int(5e5)+7, INF = 0x3f3f3f3f;
int a[maxn], head[maxn], ans[maxn], v[maxn], cnt_edge;
struct { int next, to; }edge[maxn];
void addedge(int u, int v) {
    edge[++cnt_edge] = {head[u], v}, head[u] = cnt_edge;
    edge[++cnt_edge] = {head[v], u}, head[v] = cnt_edge;
}
void dfs(int x, int pre, int d, int g) {
    ans[x] = g; int i;
    for(i=1 ; i*iif(!(a[x]%i)) {
            if(++v[a[x]/i]>=d) ans[x] = max(ans[x], a[x]/i);
            if(++v[i]>=d) ans[x] = max(ans[x], i);
        }
    if(i*i==a[x]) if(++v[i]>=d) ans[x] = max(ans[x], i);
    for(i=head[x] ; ~i ; i=edge[i].next) if(edge[i].to != pre)
            dfs(edge[i].to, x, d+1, gcd(g, a[x]));
    for(i=1 ; i*iif(!(a[x]%i)) v[a[x]/i]--, v[i]--;
    if(i*i==a[x]) v[i]--;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    printf("init! init! init!\n");
#endif
    clr(head, -1);
    int n = read;
    rep(i,1,n) a[i] = read;
    rep(i,2,n) addedge(read, read);
    dfs(1,0,0,0);
    rep(i,1,n) printf("%d%c", ans[i], i==n?'\n':' ');
    return 0;
}

你可能感兴趣的:(Codeforces,题解,思维,数据结构-树)