Codeforces 842C - Ilya And The Tree 【树上DFS】

本文探讨了一道算法题目,即在给定的生成树中,每个节点有一个初始值,求解每个节点最大美丽值的问题。美丽值定义为从根节点到目标节点路径上所有节点值的最大公约数。通过深度优先搜索实现算法,并分享了两种不同的实现思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**【题意】

给出一棵生成树,每个节点都有一个值,现在要求出每个节点的美丽值的最大值,美丽值的定义为从根节点到该节点(包含)路径上所有点的值的gcd,求解每个点时可以把路径上某一个点的值变为0。你可以认为每个点美丽值的求解是独立的。**

别人的代码ac。。

#include <bits/stdc++.h>
using namespace std;

const int maxn=2e5;

int n;
int A[maxn+10],dp[maxn+10][2],fa[maxn+10];
vector<int>g[maxn+10];
set<int>s[maxn+10];

void dfs(int v,int p,int b){
    for(int w:s[p])s[v].insert(__gcd(w,A[v]));
    s[v].insert(b);
    b=__gcd(b,A[v]);
    s[v].insert(b);
    for(int w:g[v])if(w!=p)dfs(w,v,b);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",A+i);
    int u,v;
    for(int i=1;i<n;i++){
        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 ",*s[i].rbegin());
    return 0;
}

我的代码wa4

int val[N];
const int maxn=2e5;
int fst[N],nxt[N<<1],to[N<<1],e;
vector<int>g[maxn+10];
set<int>s[maxn+10];
set<int>::iterator it;
void dfs(int u,int fa,int c){
    for(it=s[u].begin();it!=s[u].end();++it)s[u].insert(__gcd(*it,val[u]));
    s[u].insert(c);
    c=__gcd(c,val[u]);
    s[u].insert(c);
    for(int i=0;i<g[u].size();++i)if(g[u][i]!=fa)dfs(g[u][i],u,c);
}
int main(){
    int n;sf("%d",&n);
    mem(fst,-1);e=0;
    rep(i,1,n)sf("%d",&val[i]);
    rep(i,1,n-1){ int u,v;sf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
    dfs(1,0,0);
    rep(i,1,n)pf("%d%c",*s[i].rbegin(),i==n?'\n':' ');

}

原本以为可以dp ,但其实是不可以的。。。谢谢提醒

int gcd(int a,int b){ if(b>a)swap(a,b);return b==0?a:gcd(b,a%b); }
int dp[N][2],ans[N];
void add(int u,int v){
    to[e]=v;nxt[e]=fst[u];fst[u]=e++;
}
void dfs(int u,int fa){
    dp[u][0]=gcd(dp[fa][0],val[u]);
    dp[u][1]=max(dp[fa][0],gcd(dp[fa][1],val[u]));
    ans[u]=max(dp[u][0],dp[u][1]);
    for(int i=fst[u];~i;i=nxt[i]){
        int v=to[i];
        if(v==fa)continue;
        dfs(v,u);
    }
}
int main(){
    int n;sf("%d",&n);
    mem(fst,-1);e=0;
    rep(i,1,n)sf("%d",&val[i]);
    mem(dp,0);
    rep(i,1,n-1){ int u,v;sf("%d%d",&u,&v);add(u,v);add(v,u); }
    dp[1][0]=val[1];
    dfs(1,1);
    //rep(i,1,n)pf("%d %d\n",dp[i][0],dp[i][1]);
    rep(i,1,n)pf("%d%c",ans[i],i==n?'\n':' ');
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值