D01【模板】拓扑排序
拓扑排序(Topological sorting)给一个有向无环图的所有节点排序。
过程
1. 初始状态下,队列 q
装着所有入度为 0
的点,t
是一个空表
2. 每次从 q
中取出一个点 𝑢
放入 t
,然后将 𝑢
的所有出边删除
3. 若将边 (𝑢,𝑣)
删除后点 𝑣
的入度变为 0
,则将 𝑣
放入 q
中
不断重复 2,3 过程,直到队列 q
为空
检查 t 中点数是否等于 n,如果是,说明 t
中的序列就是拓扑序列,否则这个图一定有环路
应用
- 判断图中是否有环,还可以用来判断图是否是一条链
- 求带权有向无环图的最长路
- 求 AOE 网中的关键路径,估算工程完成的最短时间
求字典序最大/最小的拓扑排序
将队列替换成最大堆/最小堆实现的优先队列,此时时间复杂度为 𝑂(𝐸 +𝑉log𝑉)
有个人的家族很大,辈分关系很混乱。给出每个人的后代的信息。输出一个序列,使得每个人的后辈都比那个人后列出。
// 拓扑排序 Kahn算法 O(V+E) #include<bits/stdc++.h> using namespace std; const int N=110; int n,rd[N]; vector<int> e[N],tp; bool topo(){ queue<int> q; for(int i=1; i<=n; i++) if(!rd[i]) q.push(i); //入度为0的点均入队 while(q.size()){ int u=q.front(); q.pop(); //出队 tp.push_back(u); //记录拓扑序 for(auto v:e[u]) if(--rd[v]==0) q.push(v); //入队 } return tp.size()==n; } int main(){ cin>>n; for(int i=1,j; i<=n; i++){ while(cin>>j,j){ e[i].push_back(j); rd[j]++; //入度 } } topo(); for(int i=0; i<n; i++) cout<<tp[i]<<" "; }
设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,计算图 G 中 1,n 间的最长路径。
// 有向无环图的最长路 拓扑排序 O(n) #include<bits/stdc++.h> using namespace std; const int N=1520,M=50010; int n,m,a,b,c; vector<pair<int,int>> e[N]; int rd[N],d[N]; void topo(){ memset(d,0x80,sizeof d); //-2139062144 d[1]=0; d[n]=-1; queue<int> q; for(int i=1;i<=n;i++) if(!rd[i]) q.push(i); while(q.size()){ int u=q.front(); q.pop(); for(auto [v,w]:e[u]){ d[v]=max(d[v],d[u]+w); if(--rd[v]==0) q.push(v); } } } int main(){ cin>>n>>m; for(int i=0;i<m;i++){ cin>>a>>b>>c; e[a].push_back({b,c}); rd[b]++; //入度 } topo(); cout<<d[n]; }
给你一个食物网,你要求出这个食物网中最大食物链的数量。
#include<bits/stdc++.h> using namespace std; const int N=5005,M=80112002; int n,m,x,y,ans; int rd[N],cd[N],f[N]; //f[v]走到v点的路径条数 vector<int> e[N]; void topo(){ queue<int> q; for(int i=1;i<=n;i++) if(!rd[i]) q.push(i),f[i]=1; //起点赋值1 while(q.size()){ int u=q.front(); q.pop(); if(!cd[u]) ans=(ans+f[u])%M; //终点累计答案 for(int v:e[u]){ f[v]=(f[v]+f[u])%M; if(--rd[v]==0) q.push(v); } } } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>x>>y; e[x].push_back(y); rd[y]++; cd[x]++; } topo(); cout<<ans; }
浙公网安备 33010602011771号