1192. 奖金(拓扑排序,差分约束)

活动 - AcWing

由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。

公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。

于是Mr.Z下令召开 m 方会谈。

每位参加会谈的代表提出了自己的意见:“我认为员工 a 的奖金应该比 b 高!”

Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。

每位员工奖金最少为100元,且必须是整数。

输入格式

第一行包含整数 n,m,分别表示公司内员工数以及参会代表数。

接下来 m 行,每行 2 个整数 a,b,表示某个代表认为第 a 号员工奖金应该比第 b 号员工高。

输出格式

若无法找到合理方案,则输出“Poor Xed”;

否则输出一个数表示最少总奖金。

数据范围

1≤n≤10000
1≤m≤20000
1≤a,b≤n

输入样例:
2 1
1 2
输出样例:
201

解析: 

本题本质上是一道差分约束的问题,但由于条件特别,因此可以使用topsort来处理。 

以差分约束中的最长路为例: 

1.边权无限制,spfa,时间复杂度为 O(nm) 

2.边权非负,tarjan算法缩点+topsort,时间复杂度为 O(n+m) 

3.边权为整数,topsort,时间复杂度为O(n+m) 

 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair PII;
const int N = 1e4 + 5, M = 2e4+5, INF = 0x3f3f3f3f;
int n, m;
int h[N], e[M], ne[M], idx;
int q[N];
int d[N],dist[N];

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

bool topsort() {
	int hh = 0, tt = 0;
	for (int i = 1; i <= n; i++) {
		if (!d[i])q[tt++] = i;
	}
	while (hh < tt) {
		int t = q[hh++];
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (--d[j] == 0) {
				q[tt++] = j;
			}
			//cout << j << " " << d[j] << endl;
		}
	}
	return tt == n;
}

int main() {
	cin >> n >> m;
	memset(h, -1, sizeof h);
	for (int i = 1,a,b; i <= m; i++) {
		scanf("%d%d", &a, &b);
		add(b, a);
		d[a]++;
	}
	if (!topsort()) {
		cout << "Poor Xed" << endl;
	}
	else {
		for (int i = 1; i <= n; i++)dist[i] = 100;
		for (int i = 0; i < n; i++) {
			int j = q[i];
			for (int k = h[j]; k != -1; k = ne[k]) {
				dist[e[k]] = max(dist[e[k]], dist[j] + 1);
			}
		}
		int ret = 0;
		for (int i = 1; i <= n; i++) {
			ret += dist[i];
		}
		cout << ret << endl;
	}
	return 0;
}

你可能感兴趣的:(#,拓扑排序,#,负环,差分约束,算法)