蒲公英的叔叔是工厂的老板。随着春节的到来,他想向工人分发奖励。现在他在如何分配奖励方面遇到了麻烦。
工人们会比较他们的奖励,有些人可能会要求分配奖励,就像奖励应该比b更多.Dandelion的解决方案想要满足所有要求,当然,他想用最少的钱。每件工作都是奖励将至少为888,因为这是一个幸运数字。
输入
一行有两个整数n和m,代表作品的数量和要求的数量。(n <= 10000,m <= 20000)
然后是m行,每行包含两个整数a和b,代表一个奖励应该是不仅仅是b。
产量
对于每一个案例,打印最少钱蒲公英的叔叔需要分发。如果不可能满足所有作品的要求,打印-1。
样本输入
2 1
1 2
2 2
1 2
2 1
样本输出
1777
-1
虽说是模板题,不过还是卡了好几天······最后只好查题解做出来了。
这题的难点有三:
1、由于钱数是从低到高,所以我们要反向建图,这样做更方便
2、钱数是按层数递增的,所以要记录每层有多少人,这些人的钱数是相同的
3、这道题要判环,其判断方法就是看有无同一元素重复进队,如果有,就成环,返回-1;没有返回+1。我在这里犯傻了,想当然的以为只要每个元素的度!=0就成环,但实际上这只是成环的一种情况;还有其他情况,如:
代码:
#include <stdio.h>
#include <string.h>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1e5 + 50;
int n, m;
int ans[maxn];
int vis[maxn];
int du[maxn];
vector<int>vec[maxn];
queue<int>q;
int x, y;
int sum;
int bfs()
{
for (int i = 1; i <= n; i++) {
if (du[i] == 0) {
q.push(i);
vis[i] = 1;
}
}
int tmp = 888;//初始为888元
int cnt = 0;
while (!q.empty())
{
int qsize = q.size();//q中某层元素个数
while (qsize-- > 0) {
int top = q.front();
q.pop();
cnt++;
ans[top] = tmp;//存入该层的钱
for (int i = 0; i < vec[top].size(); i++) {
int now = vec[top][i];
du[now]--;
if (du[now] == 0 && vis[now] == 0) {
vis[now] = 1;
q.push(now);
}
}
}
tmp++;
}
if (cnt == n)//判环
return 1;
else
return -1;
}
int main()
{
ios::sync_with_stdio(false);
while (cin >> n >> m)
{
memset(vis, 0, sizeof(vis));
memset(du, 0, sizeof(du));
memset(ans, 0, sizeof(ans));
for (int i = 0; i <= n; i++)
vec[i].clear();
for (int i = 1; i <= m; i++) {
cin >> x >> y;
vec[y].push_back(x);//反向建图
du[x]++;
}
int flag=bfs();
if (flag == -1) {
cout << -1 << endl;
continue;
}
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += ans[i];
}
cout << sum << endl;;
}
return 0;
}