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

题目传送门

题意

有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。给出每个人的后代的信息。输出一个序列,使得每个人的后辈都比那个人后列出。

分析

拓扑排列是一个有向无环图的所有顶点的线性序列。

该序列需要满足以下条件:

  • 每个顶点出现且只出现一次。
  • 如果图中有一条 AB 的路径,在序列中 A 出现在 B 的前面。

拓扑排序的步骤:

计算每个点的入度
入度为 0 则加入队列
while 队列非空:
	取出队首元素并输出。
	遍历队首元素的出边,对应结点的入度 -1
	if 对应结点的入度 = 0:
		将该结点加入队列

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int to[N], nxt[N], head[N], in[N], out[N], n, u, v, cnt;

inline void add_edge(int u, int v){ // 加边函数
	to[++cnt] = v;
	nxt[cnt] = head[u];
	head[u] = cnt;
}

inline void topo(){
	queue<int> q;
	for(int i = 1; i <= n; i++)
		if(!in[i]) cout << i << ' ', q.push(i); // 判断入度是否为 0,即是否可以放入队列
	while(!q.empty()){
		u = q.front(); q.pop(); // 取出队首元素
		for(int i = head[u]; ~i; i = nxt[i]){ // 遍历所有出边
			v = to[i], in[v]--;
			if(!in[v]){
				cout << v << ' ';
				q.push(v);
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	memset(head, -1, sizeof head);
	cin >> n;
	for(int i = 1; i <= n; i++){
		int x;
		while(cin >> x){
			if(!x) break;
			add_edge(i, x);
			in[x]++, out[i]++;
		}
	}
	topo();
	return 0;
}
posted @   心灵震荡  阅读(435)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示