Codeforces 842C--Ilya And The Tree(dfs+树)

原题链接:http://codeforces.com/contest/842/problem/C

 

题意:一个以1为根节点的树,每个节点有一个值ai,定义美丽度:从根节点到这个节点的路径上所有ai的gcd,即gcd(a1,a2,a5...ai),对每个节点的美丽度,我们可以使根到这个节点的路径上一个点的ai值变为0。求所有点的最大美丽度。

 

思路:先求出没有节点变为0的情况g[i],在此基础上,如果使x节点变为0,那么它的美丽度为父节点的g[i];假设让其他在路径上的点变为0,可以知道x节点的最大美丽度是a[x]的因子,因此我们只要枚举a[x]的因子,如果这个因子在路径上出现了(深度-1)次,即我们可以把路径上其中一个a[i]变为0,剩下的a[]值都含有上述因子,那么最大美丽度一定不小于这个因子。按这个方法跑一遍dfs就行了。

 

AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<map>
 6 using namespace std;
 7 const int MAXN=2e5+5;
 8 int num[MAXN],res[MAXN],mp[MAXN],g[MAXN];
 9 vector<int> edge[MAXN];
10 bool vis[MAXN];
11 int gcd(int a, int b){
12     return (b==0)?a:gcd(b, a%b);
13 }
14 void dfs(int fa, int depth){
15     int l=edge[fa].size();
16     int u,k;
17     for(int i=0;i<l;i++)
18     {
19         u=edge[fa][i];
20         k=num[u];
21         if(!vis[u]){
22             vis[u]=1;
23             g[u]=gcd(k, g[fa]);
24             res[u]=g[fa];
25             for(int j=1;j*j<=k;j++){
26                 if(k%j==0){
27                     mp[j]++;
28                     if(mp[j]>=depth-1)    res[u]=max(res[u], j);
29                     
30                     if(j*j!=k){
31                         int t=k/j;
32                         mp[t]++;    
33                         if(mp[t]>=depth-1)    res[u]=max(res[u], t);
34                     }
35                 }
36             }
37             
38             dfs(u, depth+1);
39             
40             for(int j=1;j*j<=k;j++){
41                 if(k%j==0){
42                     mp[j]--;
43                     if(j*j!=k) mp[k/j]--;    
44                 }
45             }
46         }
47     }
48     return;
49 }
50 int main()
51 {
52     int n;
53     
54     memset(vis, 0, sizeof(vis));
55     scanf("%d", &n);
56     for(int i=1;i<=n;i++)    scanf("%d", &num[i]);
57     int a,b;
58     for(int i=0;i<n-1;i++){
59         scanf("%d %d", &a, &b);
60         edge[a].push_back(b);
61         edge[b].push_back(a);
62     }
63     vis[1]=1;
64     res[1]=num[1];
65     g[1]=num[1];
66     memset(mp, 0, sizeof(mp));
67     for(int j=1;j*j<=num[1];j++){
68         if(num[1]%j==0){
69             mp[j]++;
70             if(j*j!=num[1])
71                 mp[num[1]/j]++;
72         }
73     } 
74     dfs(1, 2);
75     printf("%d", res[1]);
76     for(int i=2;i<=n;i++)
77         printf(" %d", res[i]);
78     printf("\n");
79 }

这个题目有毒,dfs(u, depth+1)后面如果记录了因子再去进行减的操作会wa,重新枚举因子就过了。是不是我姿势不对?

posted @ 2017-09-01 15:58  Bangbangbanana  阅读(189)  评论(0编辑  收藏  举报