08年东莞特长生 奖金 题解

三世轮回 提交于 2020-01-17 23:44:27

08年东莞特长生 奖金

题目

由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,YaliYali CompanyCompany总经理Mr.ZMr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。
于是Mr.ZMr.Z下令召开mm方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工aa的奖金应该比bb高!”Mr.ZMr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。


输入

两个整数nn,mm,表示员工总数和代表数;
以下mm行,每行2个整数aa,bb,表示某个代表认为第aa号员工奖金应该比第bb号员工高。


输出

若无法找到合法方案,则输出“-1”;否则输出一个数表示最少总奖金。


样例

input
2 1
1 2

output
1


数据范围

80的数据满足nn<=1000mm<=2000
100的数据满足nn<=10000mm<=20000


解题思路

拓扑排序
SPFA求最长路径
当前点入度为0则入队
最后答案为所有最长路径的累加和

若图中有环,则输出*-1*


代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,x,y,ans;
int f[52000],rd[52000],head[52000],dis[52000];
struct c{
	int to,next;
}a[25000];
int main()
{
	memset(dis,-0x7f,sizeof(dis));
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		a[i].to=x;
		a[i].next=head[y];
		head[y]=i;  //x的工资比y高
		rd[x]++;  //统计入度
	}
	int h=0,t=0;
	for (int i=1;i<=n;i++)
	    if (rd[i]==0)  //入度为0
	    {
	    	t++;
	    	dis[i]=100;  //工资为初值100
	    	f[t]=i;  //入队
	    }
	do{
		h++;
		for (int i=head[f[h]];i;i=a[i].next)
		{
			rd[a[i].to]--;  //入度-1
			dis[a[i].to]=max(dis[a[i].to],dis[f[h]]+1);  //SPFA最长路径
			if (rd[a[i].to]==0)  //入度为0,入队
			{
				t++;
				f[t]=a[i].to;
			}
		}
	}while(h<t);
	for (int i=1;i<=n;i++)
	{
	    if (rd[i]>0)  //入度>0,存在环,输出-1
	    {
	    	cout<<-1;
	    	return 0;
	    }
	    ans+=dis[i];  //累加最长路径
	}
	cout<<ans<<endl;
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!