Codeforces Round #430 (Div. 2) C. Ilya And The Tree(dfs)

时间:2022-07-24 20:07:05

题意:给你一棵树,根节点是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;
}