拓扑排序(toposort)

杂物(拓扑排序)

前置知识
有向无环图(DAG):没有环的有向图。
对于DAG,在有的时候,对于一个节点的信息的计算,需要确保与之相连的点的信息全部被计算,这时就需要用到拓扑排序
本质是确保DAG上的点的计算顺序而非对数列排序。
队列实现拓扑排序过程

  • step1:讲入度0的点插入队列
  • step2:取出队头\(t\),遍历所有t能到达的点\(v\)
  • step3:对于每一个\(v\),维护其节点信息,同时使它入度-1,以完成删边操作
  • step4:当\(v\)入度\(0\)时,插入队列。
  • step5:跳转到step2。

注意
本题维护的节点信息是dp[i],表示第i个杂物的最早完成时间。(有动态规划那味了)
dp[i]是由它的前驱节点转移过来的。

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define bug(x) cout<<#x<<"=="<<x<<endl;
#define endl "\n"
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int inf = 0xc0c0c0c0;

const int N = 1e4 + 10;
vector<int> g[N];
int n;
int len[N];
int pre;
int rd[N];
queue<int> q;
int dp[N];

int main() {
	ios;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int c;
		cin >> c;
		cin >> len[c];

		while (cin >> pre && pre) {
			g[pre].push_back(c);
			rd[c]++;
		}
	}

	for (int i = 1; i <= n; i++) {
		if (rd[i] == 0) {
			q.push(i);
			dp[i] = len[i];
		}
	}

	while (!q.empty()) {
		auto t = q.front();
		q.pop();

		for (auto v : g[t]) {
			dp[v] = max(dp[v], dp[t] + len[v]);
			rd[v]--;
			if (rd[v] == 0) q.push(v);
		}
	}

	int ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = max(ans, dp[i]);
	}

	cout << ans << endl;
	return 0;
}
posted @ 2023-04-12 16:56  csai_H  阅读(174)  评论(0)    收藏  举报