mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
220 字
1 分钟
图论-拓扑排序
2026-08-02
  • 要求每个节点的前置节点都在这个节点之前
  • 排序前提:无环有向图
  • 拓扑排序的顺序可能不止一种
  • 拓扑排序可以判断有没有环

Kahn算法 删点法#

  • 用队列维护一个入度为0的节点的集合
  1. 初始化,队列q压入所有入度为0的点
  2. 每次从q中取出一个点x放入数组tp
  3. 然后将x的所有出边删除,若将边(x,y)删除后,y的入度变为0,则将y压入q中,重复步骤2 3
  4. 直到队列为空,若tp中的元素个数等于节点个数,则有拓扑序;否则有环
int n,m;
vector<int> adj[N],tp;
int din[N];
bool toposort(){
queue<int> q;
for(int i=1;i<=n;i++){
if(din[i]==0) q.push(i);
}
while(!q.empty()){
int x=q.front();
q.pop();
tp.push_back(x);
for(int y:adj[x]){
if(--din[y]==0) q.push(y);
}
}
return int(tp.size())==n;
}
void solve() {
cin>>n>>m;
for(int i=0;i<m;i++){
int u,v;cin>>u>>v;
adj[u].push_back(v);
din[v]++;
}
if(toposort()){
for(int v:tp){
cout<<v<<" ";
}
}
else{
cout<<"-1";
}
}

DFS 算法#

例题#

B3644 【模板】拓扑排序 / 家谱树 - 洛谷#

套上面模板就能过

P1113 [USACO02FEB] 杂务 - 洛谷#

const int N = 1e5+5;
int n;
ll costs[N];
int din[N];
vector<int> adj[N];
struct e{
int od;
ll cost;
bool operator<(const e& other) const{
return cost>other.cost;
}
};
ll toposort(){
ll ans=0;
priority_queue<e> q;
for(int i=1;i<=n;i++){
if(din[i]==0){
q.push({i,costs[i]});
}
}
while(!q.empty()){
e x=q.top();
q.pop();
int node=x.od;
ll c=x.cost;
for(int y:adj[node]){
if(--din[y]==0){
q.push({y,c+costs[y]});
ans=max(ans,c+costs[y]);
}
}
}
return ans;
}
void solve() {
cin>>n;
for(int i=1;i<=n;i++){
int u,v;cin>>u;
cin>>costs[u];
cin>>v;
while(v!=0){
adj[v].push_back(u);
din[u]++;
cin>>v;
}
}
ll ans=toposort();
cout<<ans;
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

图论-拓扑排序
https://blog.hydrodyio.xyz/posts/图论-拓扑排序/
作者
Hydroiody
发布于
2026-08-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录