杭电2467

终于自己写出来了。。。。。

其实就是拓扑排序,但要记录每层的结点;

题意:老板发奖金,但一些人有要求(就是他比谁的要高),老板决定满足一切要求,但希望花费最小,每个人的最低奖金为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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值