Apple Tree

Posted ph = x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apple Tree相关的知识,希望对你有一定的参考价值。

题意:

给一有根树,每个叶子上有一些苹果,现在要求你拿掉一些苹果,使得每一个点的 儿子的子树内的苹果数相同。

 

解法:

首先可以发现$cnt$个叶子节点之间的关系可以用$cnt-1$个独立方程表示出来。

这样相当于在方程的解中只有一个变元。

接下来求出最小整数基底:这个我们可以两遍$dfs$ + $gcd$求出。

总效率$O(nlogn)$

 

技术分享
#include <iostream>
#include <cstdio>
#include <cstring>

#define LL long long
#define N 100010
#define INF 0x3f3f3f3f3f3f3f3fLL

using namespace std;

struct edge
{
    int x,to;
}E[N<<1];

int n,totE;
int g[N];
LL f[N],a[N],sum;
bool is_leaf[N];

void addedge(int x,int y)
{
    E[++totE] = (edge){y,g[x]}; g[x]=totE;
    E[++totE] = (edge){x,g[y]}; g[y]=totE;
}

LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}

#define p E[i].x

LL calc(int x,int tp)
{
    int cnt=0;
    LL ans=1;
    for(int i=g[x];i;i=E[i].to)
        if(p!=tp)
        {
            LL tmp = calc(p,x);
            cnt++;
            if(ans/gcd(ans,tmp)<=sum/tmp)
                ans = ans/gcd(ans,tmp)*tmp;
            else return -1;
        }
    if(!cnt)
    {
        is_leaf[x]=1;
        return 1LL;
    }
    if(ans<=sum/cnt) return ans*(LL)cnt;
    else return -1;
}

void dfs(int x,int tp)
{
    int cnt=0;
    for(int i=g[x];i;i=E[i].to)
        if(p!=tp) cnt++;
    for(int i=g[x];i;i=E[i].to)
        if(p!=tp)
        {
            f[p]=f[x]/(LL)cnt;
            dfs(p,x);
        }
}

int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++) g[i]=0,is_leaf[i]=0;
        totE=0;
        sum=0;
        for(int i=1;i<=n;i++)
            scanf("%I64d",&a[i]),sum+=a[i];
        for(int i=1,x,y;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        f[1]=calc(1,1);
        if(f[1]==-1)
        {
            cout << sum << endl;
            continue;
        }
        dfs(1,1);
        LL t=INF, ans=0;
        for(int i=1;i<=n;i++)
            if(is_leaf[i])
            {
                ans += a[i];
                t = min(t, a[i]/f[i]);
            }
        ans -= t*f[1];
        cout << ans << endl;
    }
    return 0;
}


/*
t*A_i <= B_i(原先的) 
t <= B_i/A_i
*/
View Code

 

以上是关于Apple Tree的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 930 A. Peculiar apple-tree (dfs)

POJ 3321:Apple Tree(dfs序+树状数组)

POJ 2486 Apple Tree ——(树型DP)

Codeforces 931D Peculiar apple-tree(dfs+思维).cpp

poj 3321 Apple Tree

POJ2486 Apple Tree