題解 猴猴喫蘋果 長鏈剖分

題解 猴猴喫蘋果

題目描述

屏幕截圖_5.png

具體做法與心路歷程

比較簡單吧。題目要求我們每次找最長的鏈走,然後刪去點權。

kk爲根,我們發現如下性質:

  • 走的路徑一定是葉子節點
  • 每個點走後就沒有貢獻了

我們把一顆樹畫出來,觀察即可發現,這就是長鏈剖分!!!

我們把鏈的長度賦給葉子節點,然後排序即可。

注意排序的比較!!!

Code\mathcal{Code}

/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年10月30日 星期三 14時40分57秒
*******************************/
#include<cstdio>
#include<algorithm>

using namespace std;

struct IO{
    template<typename T>
    IO & operator>>(T&res)
    {
        T q=1;char ch;
        while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
        res=(ch^48);
        while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
        res*=q;
        return *this;
    }
}cin;

struct edge{
    int to,next;
    edge(int a=0,int b=0):to(a),next(b){}
};

const int maxn=5e4+10;
int n,rt,len[maxn],son[maxn],p[maxn],head[maxn],cnt,dis[maxn],stk[maxn],_top;
edge e[maxn<<1];

void add(int u,int v)
{
    e[++cnt]=edge(v,head[u]);
    head[u]=cnt;
}

void dfs(int now,int fa)
{
    len[now]=1;
    for(int i=head[now];i;i=e[i].next)
        if(e[i].to!=fa)
        {
            dfs(e[i].to,now);
            if(len[son[now]]<len[e[i].to] || (len[son[now]]==len[e[i].to] && p[e[i].to]<p[son[now]]))
                son[now]=e[i].to;
        }
    if(!son[now])
    {
        stk[++_top]=now;
        p[now]=now;
    }
    else
        p[now]=p[son[now]];
    len[now]=len[son[now]]+1;
}

void dfs(int now,int res,int fa)
{
    if(!son[now])
    {
        dis[now]=res;
        return;
    }
    else
        dfs(son[now],res+1,now);
    for(int i=head[now];i;i=e[i].next)
        if(e[i].to!=fa && e[i].to!=son[now])
            dfs(e[i].to,1,now);
}

bool cmp(int a,int b)
{
    if(dis[a]==dis[b]) return a<b;
    return dis[a]>dis[b];
}

int main()
{
    //freopen("apple.in","r",stdin);
    //freopen("apple.out","w",stdout);
    cin>>n>>rt;
    int u;
    rt++;
    for(int i=2;i<=n;i++)
    {
        cin>>u; u++;
        add(u,i);
        add(i,u);
    }
    dfs(rt,0);
    dfs(rt,1,0);
    sort(stk+1,stk+_top+1,cmp);
    printf("%d\n",rt-1);
    for(int i=1;i<=_top;i++)
        printf("%d\n",stk[i]-1);
    return 0;
}
//14:55
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章