title : 拓扑排序与关键路径
date : 2021-8-15
tags : ACM,图论
author : Linno
拓扑排序
对一个有向无环图G中所有顶点排成一个序列,使得图中任意一对顶点u和v,若边(u,v)属于E(G),那么u再线性序列中出现在v之前。这样的线性序列称为满足拓扑排序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
实现方法
//BFS:寻找入度为0的点,把这个点加入队列,在队列中对邻边进行删边操作,并反复这个操作直到所有点都被遍历。
Topological_sort(G){
统计图G中每个点的入度(可计算重边,但不可计算自环),记为degree[i]
初始化queue和result为空的队列,并将所有degree为0的点加入queue
while (!queue.empty()){
u = queue.pop() // 队首
result.push(u)
for e 是u的出边(若上面计算了重边,这里也要算,与上面一致)
v是e的指向的点
degree[v]--
if (degree[v] == 0) queue.push(v)
}
return result
}
//记忆化搜索:在每一个入度为0的点进行删边,然后往下搜索所有入度为0的点,直到遍历完所有节点。
calculate(u){
if (u 已经搜索过) return table[u]
ans = -inf
for (v 是u的出边指向的点)
ans = max(ans, value[u] + calculate(v))
标记u已经搜索过
table[u] = ans
return ans
}
for (i 是G的所有节点)
result = max(result, calculate(i))
print(result)
luoguP1137 旅行计划
在一个DAG中问i为终点能最多经过多少个节点。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m,u,v,ans[N],ru[N],vis[N];
queue<int>q;
vector<int>G[N];
void addedge(int u,int v){
G[u].push_back(v);
ru[v]++;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u>>v;
addedge(u,v);
}
for(int i=1;i<=n;i++){
ans[i]=1;
if(!ru[i]) q.push(i);
}
while(!</