题意:
Dandelion的叔叔是工厂的老板。 随着春节的到来,他想分发奖励给他的工人。 现在他在分配奖励方面遇到了麻烦。
工人们会比较他们的奖励,有些人可能会要求分配奖励,就像a的奖励应该超过b的一样.Dandelion的叔叔要满足所有的要求,当然他想用最少的钱。每个工人的奖励将至少为888,因为这是一个幸运数字。
工人们会比较他们的奖励,有些人可能会要求分配奖励,就像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;
}