终于自己写出来了。。。。。
其实就是拓扑排序,但要记录每层的结点;
题意:老板发奖金,但一些人有要求(就是他比谁的要高),老板决定满足一切要求,但希望花费最小,每个人的最低奖金为888;
解法:
如上图,1和0的为888,2和3的为889,4和5的为890,则为最小工资;
只需反着存地图,拓扑排序;首先找到所有入度为0的点,加入队列,则他们工资为888,把与他们相联系的点工资变为888+1,之后吧与之相连的边的入度减1,在把入度变为0 的加入队列,之后重复知道队列为空,
如果找到n个点,则成功,否则失败;
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct Node
{
int money;
int indg;
int n,next[102];
}map[10002];
int tosort (int n)
{
queue<int>s;
int k,i,d;
k=0;
for(i=0;i<n;i++) //把入度为0的点加入队列;
if(map[i].indg==0)
{
s.push(i);
map[i].indg--;
}
while (!s.empty())
{
k++;
i=s.front();
s.pop();
for(d=0;d<map[i].n;d++)
{
map[map[i].next[d]].indg--;
map[map[i].next[d]].money=map[i].money+1; //把与之相连的点的钱+1;
if(map[map[i].next[d]].indg==0) //加入入度变为0的结点;
s.push(map[i].next[d]);
}
}
if(k<n)
return 0;
return 1;
}
int main()
{
int n,m,i,x,y,res;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(map,0,sizeof(map));
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
if(x!=y)
{
map[x-1].indg++; //反着存;边从0开始
map[y-1].next[map[y-1].n]=x-1;
map[y-1].n++;
}
}
if(!tosort(n))
printf("-1\n");
else
{
for(i=res=0;i<n;i++)
res+=map[i].money+888;
printf("%d\n",res);
}
}
return 0;
}