HDU-2647-Reward(拓扑排序发工资)

题目

有n个工人,有些人有要求要比别的某个人工资高,满足这些全部要求最少发的工资,底线是888。第一行n,m 剩下的m行要求,不能满足输出-1;否则输出最小发工资数。
Sample Input
2 1
1 2
2 2
1 2
2 1
Sample Output
1777
-1

从初始入度便为0的点到达入度减到0的点长的话。在队列中就是最后一步导致入度减到0的,就保证 f[y] = f[x] + 1 的正确性。
a比b工资高, 应该b指向a, b在a前面,f[y]=f[x]+1,代表y的层次。队里面出来的元素个数cnt==n说明没有环,则会有方案。其实有环cnt<n;

#include <queue>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define  m(a,b) memset(a,b,sizeof a)
#define sdd(a,b) scanf("%d%d",&a,&b)
typedef long long ll;
using namespace std;
const int N=10000+2;
int tot,n,m;
int head[N],f[N],in[N];
struct Edge{int to,nex;}edge[N*2];
void add(int from,int to)
{
    edge[++tot]=(Edge){to,head[from]};head[from]=tot;
    in[to]++;
}
queue<int>q;
void topo()
{
    ll sum=0;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(!in[i])
        {
            q.push(i);
            f[i]=0;
        }
    } 
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        sum+=f[x];
        cnt++;
        for(int i=head[x];i;i=edge[i].nex)
        {
            int y=edge[i].to;
            in[y]--;
            if(!in[y])
            {
                q.push(y);
                f[y]=f[x]+1;
            }
        }
    }
    if(cnt==n)//  写cnt>=n也不会错
        printf("%lld\n",sum+888*n);
    else
        printf("-1\n");
}
int main()
{
    while(~sdd(n,m))
    {
        for(int i=1;i<=n;i++)
        {
            head[i]=0;
            in[i]=0;
        }
        tot=0;
        while(!q.empty())
            q.pop();
        while(m--)
        {
            int a,b;
            sdd(a,b);
            add(b,a);
        }
        topo();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值