有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();
}
}