hdu2647

蒲公英的叔叔是工厂的老板。随着春节的到来,他想向工人分发奖励。现在他在如何分配奖励方面遇到了麻烦。 
工人们会比较他们的奖励,有些人可能会要求分配奖励,就像奖励应该比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 <assert.h>
#include <string.h>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>
#include<map>
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;;
	}
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zsnowwolfy/article/details/82529577