1 条题解

  • 0
    @ 2021-6-15 14:10:55

    C++ :

    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    vector<int> a[100001],shi[100001],son[100001];
    queue<int> ling;
    int ru[100001],fa[100001][20],deep[100001],ans[100001];
    int LCA(int aa,int bb)//用倍增法求LCA
    {
        if(deep[aa]>deep[bb]) swap(aa,bb);
        int ff=deep[bb]-deep[aa];
        for(int i=0;(1<<i)<=ff;i++)
            if((1<<i)&ff)
                bb=fa[bb][i];
        if(aa!=bb)
        {
            for(int i=18;i>=0;i--)
                if(fa[aa][i]!=fa[bb][i])
                {
                    aa=fa[aa][i];
                    bb=fa[bb][i];
                }
            aa=fa[aa][0];
        }
        return aa;
    }
    void dfs(int o)//树上前缀和
    {
        if(son[o].empty()) {ans[o]=1;return;}
        for(int i=0;i<son[o].size();i++)
        {
            if(ans[son[o][i]]==0) dfs(son[o][i]);
            ans[o]+=ans[son[o][i]];
        }
        ans[o]++;
    }
    int main()
    {
        int n;
        cin>>n;
        memset(ru,0,sizeof(ru));
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            while(x!=0)
            {
                a[x].push_back(i);
                ru[i]++;
                shi[i].push_back(x);
                scanf("%d",&x);
            }
        }
        memset(fa,0,sizeof(fa));
        memset(deep,0,sizeof(deep));
        deep[70000]=1;
        for(int i=1;i<=n;i++)
            if(ru[i]==0) 
            {
                ling.push(i);
                shi[i].push_back(70000);
            }
        while(!ling.empty())//拓扑排序(同时加点)
        {
            int yu=ling.front();
            ling.pop();
            int lca=shi[yu][0];
            if(shi[yu].size()!=1)
                for(int i=1;i<shi[yu].size();i++)
                    lca=LCA(lca,shi[yu][i]);//把每个节点都连接在它的所有食物的LCA上
            deep[yu]=deep[lca]+1;//新加入节点的深度
            fa[yu][0]=lca;
            son[lca].push_back(yu);
            for(int i=1;i<=18;i++)//更新新加入节点的倍增数组
                if(fa[yu][i-1])
                    fa[yu][i]=fa[fa[yu][i-1]][i-1];
            for(int i=0;i<a[yu].size();i++)
            {
                ru[a[yu][i]]--;
                if(ru[a[yu][i]]==0) ling.push(a[yu][i]);
            }
        }
        memset(ans,0,sizeof(ans));
        dfs(70000);//求树上前缀和
        for(int i=1;i<=n;i++) cout<<(ans[i]-1)<<endl;
        return 0;
    }
    
    • 1

    信息

    ID
    976
    时间
    1000ms
    内存
    128MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者