1. 程式人生 > 實用技巧 >【獎金】題解

【獎金】題解

題目描述


由於無敵的凡凡在2005年世界英俊帥氣男總決選中勝出,Yali Company總經理Mr.Z心情好,決定給每位員工發獎金。公司決定以每個人本年在公司的貢獻為標準來計算他們得到獎金的多少。
於是Mr.Z下令召開m方會談。每位參加會談的代表提出了自己的意見:“我認為員工a的獎金應該比b高!”Mr.Z決定要找出一種獎金方案,滿足各位代表的意見,且同時使得總獎金數最少。每位員工獎金最少為100元。


輸入格式
第一行兩個整數n,m,表示員工總數和代表數;
以下m行,每行2個整數a,b,表示某個代表認為第a號員工獎金應該比第b號員工高。


輸出格式


若無法找到合理方案,則輸出“Poor Xed”;否則輸出一個數表示最少總獎金。


樣例輸入
2 1
1 2


樣例輸出
201


程式碼 + 分析

和往常一樣,詳解就附在程式碼上了。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 10005;

vector <int> G[MAXN];
queue <int> q;
int tot[MAXN];
int cost[MAXN];
int len = 1;
int n, m;

void topsort () {
	for (int i = 1; i <= n; i++) {
		if (!tot[i]) {
			q.push (i); 
		}//假如這個點沒有度(前驅),就把他入隊
		cost[i] = 100;//題目所說,工資最少為 100
	}
    //就是常規操作
	while (!q.empty()) {
		int x = q.front ();//取出隊頭
		q.pop();//彈出
		len ++;//答案的長度累加
		for (int i = 0; i < G[x].size(); i++) {
			if (tot[G[x][i]]) { //假如與它相連的還有沒處理完的
				tot[G[x][i]] --;//那麼就應該把他的度減少一個(比他先處理的人要少一個)(因為我們是從小往大求的)
				if (tot[G[x][i]] == 0) {//假如他就是下一個要處理的人
					q.push (G[x][i]);//就把他裝進佇列,繼續搜尋
					cost[G[x][i]] = max(cost[G[x][i]], cost[x] + 1);//他的答案應該就等於上一個人的錢數加 1 塊錢
				}
			}
		}
	}
}

int main() {
	scanf("%d %d", &n, &m);//輸入
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		G[y].push_back(x);//假如 x 比 y 多,那麼 x 就應該在 y 的後面,所以把 x 存進 y 裡
		tot[x] ++;//x 的度累加
	}
	topsort ();//拓撲
	if (len < n) {
		printf("Poor Xed\n");
		return 0;
	}//假如答案的長度還沒有 n ,那麼說明無解
	int sum_ = 0;
	for (int i = 1; i <= n; i++) {
		sum_ += cost[i];
	}//累加答案
	printf("%d", sum_);//完美結束
	return 0;
}