CF842C Ilya And The Tree

思路:

1. 如果根节点是0,那么可以通过一次dfs计算出所有节点的最大值。

2. 如果根节点不是0,那么其余各点的最大值一定是根节点的一个因子。首先计算出根节点的所有因子。在dfs到一个深度为d的节点v时,遍历所有因子:对于因子x,p表示从根节点到达v的路径中能够被x整除的节点个数。如果p >= d - 1,则x就是当前节点的一个候选最大值(d-1是因为可以把路径中其中一个数替换为0)。

于是通过两次dfs即可得出答案。复杂度O(n * sqrt(n))。在dfs的过程中,要注意维护全局变量。dfs到下一个分支时,要把上一个分支对全局变量造成的影响消除。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[200005], val[200005];
 4 vector<int> tree[200005];
 5 int vis[200005];
 6 int divisors[1005];
 7 
 8 void dfs(int cur, int div)
 9 {
10     vis[cur] = 1;
11     for (int i = 0; i < tree[cur].size(); i++)
12     {
13         int tmp = tree[cur][i];
14         if (vis[tmp]) continue;
15         val[tmp] = __gcd(div, a[tmp]);
16         dfs(tmp, val[tmp]);
17     }
18 }
19 
20 void dfs2(int cur, int d, vector<int>& v)
21 {
22     vis[cur] = 1;
23     for (int i = 0; i < tree[cur].size(); i++)
24     {
25         int tmp = tree[cur][i];
26         if (vis[tmp]) continue;
27          for (int j = 0; j < v.size(); j++)
28         {
29             if (a[tmp] % v[j] == 0) divisors[j]++;
30             if (divisors[j] >= d) val[tmp] = max(val[tmp], v[j]);
31         }
32         dfs2(tmp, d + 1, v);
33         for (int j = 0; j < v.size(); j++)
34             if (a[tmp] % v[j] == 0) divisors[j]--;
35     }
36 }
37 
38 int main()
39 {
40     int n, x, y;
41     while (cin >> n)
42     {
43         for (int i = 1; i <= n; i++)
44             tree[i].clear();
45         for (int i = 1; i <= n; i++)
46             cin >> a[i];
47         for (int i = 0; i < n - 1; i++)
48         {
49             cin >> x >> y;
50             tree[x].push_back(y);
51             tree[y].push_back(x);
52         }
53         int tmp = a[1];
54         a[1] = 0;
55         memset(vis, 0, sizeof vis);
56         dfs(1, 0);
57         a[1] = val[1] = tmp;
58         vector<int> v;
59         for (int i = 1; i * i <= a[1]; i++)
60         {
61             if (a[1] % i == 0)
62             {
63                 v.push_back(i);
64                 if (a[1] / i != i) v.push_back(a[1] / i);
65             }
66         }
67         sort(v.begin(), v.end());
68         for (int i = 0; i < v.size(); i++) divisors[i] = 1;
69         memset(vis, 0, sizeof vis);
70         dfs2(1, 1, v);
71         for (int i = 1; i <= n; i++)
72             cout << val[i] << " ";
73         cout << endl;
74     }
75     return 0;
76 }
原文地址:https://www.cnblogs.com/wangyiming/p/7469569.html