Problem: 奖金

Problem: 奖金

Time Limit: 1 Sec  Memory Limit: 128 MB
[Submit][Status][Web Board]

Description

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

Input

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

Output

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

Sample Input

2 1
1 2

Sample Output

201

HINT

拓扑排序
Input

6 6
1 2
2 3
1 3
4 6
3 4
3 5

Output

610

Pictrue

  5
  ↓
┌─3←4←6
↓ ↓
1←2

Hint

---0---
  0
  ↓
┌─2←1←0
↓ ↓
2←1
ans=200
---1---
┌─1←1←0
↓ ↓
2←1
ans=301
---2---
┌─1←0
↓ ↓
2←1
ans=403
---3---
┌─0
↓ ↓
2←1
ans=506
---4---
1←0
ans=610

code

#include<stdio.h>
#include<queue>
using namespace std;
struct node { int to,nxt; } e[10001<<1];
int cnt,n,m,sum,num,ans;
int deg[10001],head[10001];
queue<int>q;
int vis[10001];
void add(int x,int y) {
	e[++cnt]=(node) { y,head[x] };
	head[x]=cnt;
	deg[y]++;
}
int main(void) {
	register int i;
	int x,y,flag;
	scanf("%d %d",&n,&m);
	for(i=1; i<=m; i++) {
		scanf("%d %d",&x,&y);
		add(y,x);
	}
	while(1) {
		flag=0;
		for(i=1; i<=n; i++)
			if(!deg[i]&&!vis[i]) {
				q.push(i);
				flag=vis[i]=1;
				ans+=100; //基本奖金
			}
		if(!flag) break;
		while(!q.empty()) {
			x=q.front(); //取出队列头
			q.pop();
			num++;
			ans+=sum;
			for(i=head[x]; i; i=e[i].nxt)
				deg[e[i].to]--;
		}
		sum++;
	}
	if(num==n) printf("%d
",ans);
	else puts("Poor Xed");
	return 0;
}
原文地址:https://www.cnblogs.com/ZhaoChongyan/p/11740390.html