【SSL】1325奖金(拓扑排序)

【SSL】1325奖金(拓扑排序)

Time Limit:1000MS
Memory Limit:65536K

Description

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

Input

两个整数n,m,表示员工总数和代表数;
以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。

Output

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

Sample Input

2 1
1 2

Sample Output

201

Hint

80%的数据满足n<=1000,m<=2000;
100%的数据满足n<=10000,m<=20000。

思路

做拓扑排序
这个算法描述如下:
1.初始化一个int[] inDegree保存每一个结点的入度。
2.对于图中的每一个结点的子结点,将其子结点的入度加1。
3.选取入度为0的结点开始遍历,并将该节点加入输出。
4.对于遍历过的每个结点,更新其子结点的入度:将子结点的入度减1。
6.重复步骤3,直到遍历完所有的结点。
如果无法遍历完所有的结点,则意味着当前的图不是有向无环图。不存在拓扑排序。
当且仅当一个有向图为有向无环图(directed acyclic graph,或称DAG)时,才能得到对应于该图的拓扑排序。每一个有向无环图都至少存在一种拓扑排序。

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int ans[100010],sum=0,tot=0,n,m,head[100010],ins[100010];
queue<int> q;
struct jgt
{
    
    
	int x,y,nxt;
}f[200010];
void input()
{
    
    
	int i;
	memset(ins,0,sizeof(ins));
	memset(ans,0,sizeof(ans));
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)
	{
    
    
		tot++;
		scanf("%d%d",&f[tot].y,&f[tot].x);
		f[tot].nxt=head[f[tot].x];
		head[f[tot].x]=tot;
		ins[f[tot].y]++;
	}
	return;
}
void topsort()
{
    
    
	int i;
	for(i=1;i<=n;i++)
		if(!ins[i])
			q.push(i);
	for(;!q.empty();q.pop(),sum++)
	{
    
    
		for(i=head[q.front()];i;i=f[i].nxt)//更新入度 
		{
    
    
			ins[f[i].y]--;
			if(!ins[f[i].y])//当能够到达这个点的所有点都遍历过后将这个点加入队列
			{
    
    
				ans[f[i].y]=ans[q.front()]+1;
				q.push(f[i].y);
			}
		}
	}
	return;
}
void output()
{
    
    
	int i,answer=n*100;
	if(sum<n)//循环依赖 
	{
    
    
		printf("-1");
		return;
	}
	for(i=1;i<=n;i++)
		answer+=ans[i];
	printf("%d",answer);
	return;
}
int main()
{
    
    
	input();
	topsort();
	output();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/112394203