1. 程式人生 > 其它 >演算法提高課 拓撲排序專題(4/4)

演算法提高課 拓撲排序專題(4/4)

AcWing 1191. 家譜樹

題意:

  • 裸拓撲排序

AcWing 1192. 獎金

題意:

  • 給定了\(m\)組要求\(a,b\),每次要求\(a\)的獎金比\(b\)的高,求出滿足所有要求的最小花費
  • 每組要求看作\(b\rightarrow a\)的一條有向邊,令所有入度為0的點獎勵為最小值\(100\),然後拓撲排序的過程中不斷更新後繼節點的答案即可,為了滿足所有要求更新時取個\(max\)
  • 可行性直接判斷最後拓撲排序後的陣列能否有\(n\)個數即可
#include <bits/stdc++.h>

using namespace std;

const int N = 10010;
const int M = 20010;

int head[N],to[M],nxt[M],tot,ind[N],award[N],n,m;

void add(int u,int v) {
	to[++tot] = v,nxt[tot] = head[u],head[u] = tot;
	ind[v] ++;
}

bool toposort(vector<int>& vec) {
	queue<int>q;
	for(int i = 1;i <= n;i ++) {
		if(!ind[i]) { 
			// cout << i << '\n';
			award[i] = 100;
			q.push(i);
		}
	}
	// vector<int>ans;
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		vec.push_back(u);
		for(int i = head[u];i;i = nxt[i]) {
			int v = to[i];
			award[v] = max(award[v],award[u] + 1);
			if(--ind[v] == 0) {
				q.push(v);
			}
		}
	}
	// cout << vec.size() << '\n';
	return vec.size() == n;
}

int main() {
	cin >> n >> m;
	while(m --) { 
		int a,b; cin >> a >> b;
		add(b,a);
	}
	vector<int>ans;
	if(toposort(ans)) {
		int s = 0;
		for(auto i : ans) s += award[i];
		cout << s << '\n';
	} else {
		cout <<"Poor Xed\n";
	}
	return 0;
}