AcWing 1191. 家谱树
\(\color{black}Acwing 1191.家谱树\)
题意转化
给出一个有 \(n\) 个节点的有向图,输出一个序列,使得序列中任意父节点都排在子节点前
题目分析
拓扑排序模板题,进行排序后输出即可。
拓扑排序
给出一个 \(DAG\) (有向无环图),如果从节点 \(u\) 到 \(v\) 有边,那么认为 \(v\) 依赖于 \(u\), 如果从节点 \(u\) 到 \(v\) 有简单路径,那么认为 \(v\) 间接依赖于 \(u\), 而拓扑排序的目标即是将所有结点排序,使得排在前面的节点不能依赖于排在后面的节点,我们称此序列为 拓扑序列。
下面给出拓扑排序的步骤。
\(1.\) 选择图中一个入度为 \(0\) 的点
\(2.\) 输出此顶点,并删除此节点及该节点的所有出边
下边给出拓扑排序的一个例子。

选择点 \(1\), 输出并删除此节点及该节点的所有出边。

选择点 \(2\), 输出并删除此节点及该节点的所有出边。

选择点 \(3\), 输出并删除此节点及该节点的所有出边。
选择点 \(4\), 输出并删除此节点及该节点的所有出边。
至此,拓扑排序结束。
个人代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 5;
#define ll long long
int a[N];
int in[N]; // 存储每一个点的入度
vector <int> G[N];
int n;
void toposort()
{
vector <int> ans; // 存储答案
queue <int> q; // 存储入度为 0 的点
for(int i = 1; i <= n; i++)
{
if(in[i] == 0)
{
q.push(i);
}
}
while(!q.empty())
{
int u = q.front();
q.pop();
ans.push_back(u);
for(auto x : G[u]) // 将与点 u 相邻的点入度减一
{
if(in[x] > 0)
{
in[x]--;
if(in[x] == 0)
{
q.push(x);
}
}
}
}
for(auto i : ans)
{
cout << i << ' ';
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++)
{
while(1)
{
int v;
cin >> v;
if(v == 0)
{
break;
}
G[i].push_back(v);
in[v]++;
}
}
toposort();
return 0;
}

浙公网安备 33010602011771号