Codeforces 842C Ilya And The Tree(树上DP+因子个数估计)

34 篇文章 1 订阅
21 篇文章 0 订阅

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(Vd) ,其中 V 为顶点数,d为因子数。

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;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值