拓扑排序:首先将图中入度为 0 的点压入队列中,每次从队列中 pop 出一个点并将该点所连接的点入度都减一,若入度减到 0 则压入队列,直到队列为空,那么将每一次 pop 出的点记录下来就是该图的拓扑排序。如果要求字典序最小将队列改为优先队列即可。
求最长路:动态规划 设当前队列中 pop 出的点为 u ,与 u 连接的点 v ,那么 dis[v] = max(dis[v], dis[u] + edges[u][v]) 。则记录 dis 中最大值就是最长路。
代码:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
#define int ll
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXM 1000000 + 10
#define MAXN 100000 + 10
const ll mod = 1e9 + 7;
#define P pair<int, int>
#define fir first
#define sec second
int n;
vector<int> G[MAXN];
int num[MAXN], in[MAXN];
int dis[MAXN];
int ans;
signed main()
{
cin >> n;
for(int i = 1; i <= n; i ++) {
int pre; cin >> num[i] >> num[i];
while(cin >> pre, pre) {
G[pre].push_back(i);
in[i] ++;
}
}
queue<int> Q;
for(int i = 1; i <= n; i ++) {
if(!in[i]) {
Q.push(i);
dis[i] = num[i];
}
}
while(!Q.empty()) {
int now = Q.front();
Q.pop();
for(int i = 0; i < G[now].size(); i ++) {
in[G[now][i]] --;
if(!in[G[now][i]]) Q.push(G[now][i]);
dis[G[now][i]] = max(dis[G[now][i]], dis[now] + num[G[now][i]]);
ans = max(ans, dis[G[now][i]]);
}
}
cout << ans << endl;
}
/*
The WAM is F**KING interesting .
*/