GYM 101128 A.Promotions【思维+暴力】

本文针对一组员工及其升级依赖关系,提出了一种算法来确定不同目标升级人数时的必要条件及不可达成的情况。通过构建反向图和遍历,计算出在特定条件下能够升级的员工数量。

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



题目大意:

我们现在有E个员工,有P个关系,每个关系x,y表示x想要升级的话,y必须先升级。

问此时:

①如果我们希望A个人升级的话,必须需要升级的人数。

②如果我们希望B个人升级的话,必须需要升级的人数。

③如果我们希望B个人升级的话,有多少人一定升级不了。


思路:


设定三个要求的值为ansa,ansb,ansc;


①我们反向建图,然后O(n^2)去跑出ned【i】【j】,ned【i】【j】表示升级i之前,是否需要先升级j,如果需要,ned【i】【j】=1;


②然后我们很容易能够考虑到ansc的求法,我们再维护一个数组need【i】,表示升级i之前,必须需要升级的人数,那么如果有:need【i】>=B,也就是说我们要升级i这个人时候,需要之前先升级至少B个人才能升级这个人,那么这个人一定升级不了,那么ansc=Σneed【i 】>=B?1:0


③那么我们稍微考虑一下也不难想到,我们再维护一个数组nott【i】,表示升级了i之前,最多可以升级的人数,那么如果有nott【i】<A,那么ansa++,同理如果有nott【i】<B,那么ansb++.


过程维护一下,注意初始化就没别的什么了。。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
int vis[5005];
int need[5005];
int nott[5005];
vector<int>mp[5005];
int ned[5005][5005];
int A,B,n,m;
void Dfs(int u,int root)
{
    ned[root][u]=1;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(vis[v]==0)
        {
            vis[v]=1;
            Dfs(v,root);
        }
    }
}
int main()
{
    while(~scanf("%d%d%d%d",&A,&B,&n,&m))
    {
        memset(nott,0,sizeof(nott));
        memset(ned,0,sizeof(ned));
        memset(need,0,sizeof(need));
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x++;y++;
            mp[y].push_back(x);
        }
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            Dfs(i,i);
        }
        int ansa,ansb,ansc;
        ansa=ansb=ansc=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                if(ned[i][j]==1)
                {
                    need[i]++;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                if(ned[i][j]==0)
                {
                    nott[j]++;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(nott[i]<A)ansa++;
            if(nott[i]<B)ansb++;
            if(need[i]>=B)ansc++;
        }
        printf("%d\n%d\n%d\n",ansa,ansb,ansc);
    }
}
/*
3 4 7 8
0 4
1 2
1 5
5 2
6 4
0 1
2 3
4 5

*/










评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值