Birokracija 拓扑排序

28 篇文章 0 订阅
1 篇文章 0 订阅

题意:第一行输入n,表示有n个人,编号为1~n,其中1是老板,他没有上司。
第二行输入n-1个数字,其中a[i]表示a[i]是i的上司。
每次分配任务时,都从老板(1号)开始将任务推给自己的下级(当有多个下级时选择编号较小的)直到分配到最底层的员工,由最底层的员工开始执行。每次执行这个任务的员工可以获得1元,他的上司获得2元,上司的上司3元……执行完任务后该员工就会离开这个公司,最后整个公司只剩下老板,老板执行了他的第一个任务后也离开了。问最后每个人赚的钱分别是多少。
思路:上一级每次都比下一级多赚一元,如果能够知道到下一级自己执行任务为止下一级总共赚了多少次钱,就可以知道上一级比下一级多赚了多少钱。上一级赚的钱一定是下一级赚的钱+下一级赚钱的次数,即上级赚的钱=∑(下级赚的钱+下级自己加上下级的下级有多少个)

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
stack<ll> st;
ll n;
ll in[200005];
ll fa[200005];
ll ans[200005];
ll side[200005];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);cout.tie(0); 
    memset(ans,0,sizeof(ans));
    memset(in,0,sizeof(in));
    while(!st.empty()) st.pop();
    cin >> n;
    for(int i=2; i<=n; i++)
    {
        ll a;
        cin >> a;
        fa[i]=a;
        in[a]++;
    }
    fa[1]=0;
    for(int i=1;i<=n;i++)
    if(in[i]==0) 
    st.push(i);
    while(!st.empty())
    {
        ll x=st.top();//x做任务 
        st.pop();
        ll f=fa[x];//f是x的上一级 
        side[x]++;//表示x有多少个下级(包括x自己) 
        ans[x]++;
        side[f]+=side[x];
        ans[f]+=side[x]+ans[x];
        in[f]--;
        if(in[f]==0) st.push(f);    
    }
    for(int i=1;i<=n;i++)
    cout<<ans[i]<<" ";
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值