codeforces 842C. Ilya And The Tree(dfs,dp)

题目链接

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

题意:给出 \(n\) 个结点的一棵树,每个结点有权值,每个结点的魅力值就是根结点到该结点的路径上点的 \(gcd\) ,现可以进行一次操作:将树上某个结点权值变成0,或者保持所有点权值不变,问每个结点可能的最大的魅力值(每个结点的询问独立,即操作可以不同)。

题解:由于是求 \(gcd\) ,当前结点的最大值并不能导出子结点最优值,比如

7

63 63 63 63 9 7 7
1 2
2 3
3 4
4 5
5 6
6 7

虽然结点6的最优值为9,但结点7的最优值应该为7.

所以,此处用一个 \(vector\)\(set\) 存到该结点路径上执行一次操作可能得到的所有值,由于因数有限,因此这样做是可以的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=2e5+100;
int head[maxn];
struct edge
{
    int to,next;
}e[maxn*2];   //
int tol=0;
void add(int u,int v)
{
    e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
}
int v[maxn];
int d[maxn];
VI g[maxn]; //g[u]用于存从根结点到结点u执行一次操作可能得到的gcd集合
int gcd(int a,int b)
{
    if(a<b) swap(a,b);
    return b==0? a:gcd(b,a%b);
}
void dfs(int u,int f)
{
    d[u]=gcd(d[f],v[u]);
    for(int i=0;i<g[f].size();i++)
    {
        g[u].pb(gcd(g[f][i],v[u]));
    }
    g[u].pb(d[f]);
    sort(g[u].begin(),g[u].end());
    g[u].erase(unique(g[u].begin(),g[u].end()),g[u].end());
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==f) continue;
        dfs(v,u);
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    rep(i,1,n+1) scanf("%d",&v[i]);
    rep(i,1,n)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    rep(i,1,n+1)
    {
        if(!g[i].empty())
            d[i]=max(d[i],g[i].back());
        printf("%d ",d[i]);
    }
    puts("");
    return 0;
}
posted @ 2017-08-30 14:18  tarjan's  阅读(168)  评论(0编辑  收藏  举报