zoukankan      html  css  js  c++  java
  • 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("
    ");
    79 }

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

  • 相关阅读:
    dotnet 使用 MessagePack 序列化对象
    dotnet 使用 MessagePack 序列化对象
    PHP die() 函数
    PHP defined() 函数
    PHP define() 函数
    PHP constant() 函数
    PHP connection_status() 函数
    查看物理CPU个数、核数、逻辑CPU个数
    CF997C Sky Full of Stars
    dotnet 使用 lz4net 压缩 Stream 或文件
  • 原文地址:https://www.cnblogs.com/MasterSpark/p/7463640.html
Copyright © 2011-2022 走看看