频道栏目
首页 > 程序开发 > 软件开发 > C语言 > 正文
C题解:有一棵树,一开始每个点有一个初始值,每一个点的新数为它到树顶的路径中的所有数,去掉一个数后的最大公因数中的最大值
2018-02-11 11:46:16      个评论    来源:yzyyylx的博客  
收藏   我要投稿

题意

有一棵树,一开始每个点有一个初始值,每一个点的新数为它到树顶的路径中的所有数,去掉一个数后的最大公因数中的最大值.

做法

因为要去掉一个数,所以一个个枚举显然不显示,因而可以在dfs时记录一下此时的点到根的数的因数个数,也就是每扫到一个点都将其分解质因数(记得回溯),若新增的因数的个数达到其深度-1,则这个数可用,在分解的同时找到最大的.

但还要考虑不是新增的因数,即去掉的数是这个点的数,那么此时的答案为其父节点到根 的所有数中的最大公约数,比较两个数取最大值即可.

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200100
using namespace std;

int n,m,dn[N],bb,first[N],g[N],deep[N],cnt[N],ans[N];
struct Bn
{
    int to,next;
}bn[N*2];

inline void add(int u,int v)
{
    bb++;
    bn[bb].to=v;
    bn[bb].next=first[u];
    first[u]=bb;
}

inline int fj(int u,int v)
{
    int i,res=1;
    cnt[u]++;
    if(cnt[u]>=v) res=u;
    for(i=2;i*i<=u;i++)
    {
        if(u%i==0)
        {
            cnt[i]++;
            if(cnt[i]>=v) res=max(res,i);
            if(i*i!=u)
            {
                cnt[u/i]++;
                if(cnt[u/i]>=v) res=max(res,u/i);
            }
        }
    }
    return res;
}

inline void ffj(int u)
{
    int i;
    cnt[u]--;
    for(i=2;i*i<=u;i++)
    {
        if(u%i==0)
        {
            cnt[i]--;
            if(i*i!=u)
            {
                cnt[u/i]--;
            }
        }
    }
}

inline int gcd(int u,int v)
{
    if(u<v) swap(u,v);
    for(;u!=v&&u&&v;swap(u,v))
    {
        u%=v;
    }
    return max(u,v);
}

void dfs(int now,int last)
{
    int p,q;
    for(p=first[now];p!=-1;p=bn[p].next)
    {
        if(bn[p].to==last) continue;
        deep[bn[p].to]=deep[now]+1;
        g[bn[p].to]=gcd(dn[bn[p].to],g[now]);

        ans[bn[p].to]=fj(dn[bn[p].to],deep[now]);
        ans[bn[p].to]=max(ans[bn[p].to],g[now]);
        dfs(bn[p].to,now);
        ffj(dn[bn[p].to]);
    }
}

int main()
{
    memset(first,-1,sizeof(first));
    register int i,j,p,q;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&dn[i]);
    }
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&p,&q);
        add(p,q);
        add(q,p);
    }
    deep[1]=1;
    g[1]=ans[1]=dn[1];
    fj(dn[1],1);
    dfs(1,-1);
    for(i=1;i<=n;i++)
    {
        printf("%d ",ans[i]);
    }
}
点击复制链接 与好友分享!回本站首页
上一篇:C语言经典链表面试题分享
下一篇:C语言实现单链表的代码教程
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站