HDU 2647 Rewards

题意:
    Dandelion的叔叔是工厂的老板。 随着春节的到来,他想分发奖励给他的工人。 现在他在分配奖励方面遇到了麻烦。
工人们会比较他们的奖励,有些人可能会要求分配奖励,就像a的奖励应该超过b的一样.Dandelion的叔叔要满足所有的要求,当然他想用最少的钱。每个工人的奖励将至少为888,因为这是一个幸运数字。
思路:
    要满足a的奖励超过b的奖励,可以采用建立有向图进行拓扑排序的方法。但注意题中给定的是奖励的最小值,而拓扑排序每次操作是取出入度为0的点排序,若按从大到小的方向建图,奖励最少的人将位于树的叶节点,故需要反向建图,且定义标记数组存储节点的层数。
ps:此处操作时一开始想到的是在加边的时候将起点和终点反向,结果答案有误。后来直接在输入的时候把变量名字换一下就对了,emmm。。。

下面放代码: 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=10000+15;
int n,m;
int tol;
int indeg[maxn];//入度
int money[maxn];//标记同一层的点 
struct node
{
	int u,v; 
}edge[maxn*2];
void addedge(int u,int v)
{ 
	edge[tol].u=u;
	edge[tol++].v=v;
	indeg[v]++;
}
int topo()
{
	queue <int> q;
	int cnt=0,sum=0;
	for(int i=1;i<=n;i++)
	{
		if(indeg[i]==0)
		q.push(i);
	}
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		cnt++;//计数 
		sum+=(888+money[now]);
		for(int i=0;i<tol;i++)
		{
			if(edge[i].u==now)
			{
				indeg[edge[i].v]--;//删边 
				if(indeg[edge[i].v]==0)//入度为0
				{
					q.push(edge[i].v);
					money[edge[i].v]=money[now]+1; 
				} 
			}
		}
	}
	if(cnt==n)//存在 
	return sum;
	else
	return -1;
}
int main()
{
	int begin,end;
	while(~scanf("%d%d",&n,&m))
	{
		memset(indeg,0,sizeof(indeg));
		memset(money,0,sizeof(money));
		tol=0;
		while(m--)
		{
			scanf("%d%d",&end,&begin);
			addedge(begin,end);
		}
		printf("%d\n",topo());
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41279172/article/details/80739053