关于拓扑排序
定义
拓扑排序
在一个 DAG(有向无环图) 中,我们将图中的顶点以线性方式进行排序,使得对于任何的顶点 \({u}\) 到 \({v}\) 的有向边 \({(u,v)}\), 都可以有 \({u}\) 在 \({v}\) 的前面。
还有给定一个 DAG,如果从 \({i}\) 到 \({j}\) 有边,则认为 \({j}\) 依赖于 \({i}\)。如果 \({i}\) 到 \({j}\) 有路径(\({i}\) 可达 \({j}\)),则称 \({j}\) 间接依赖于 \({i}\)。
拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点。
补充
\({\large 关于AOV网}\)
在日常生活中,一项大的工程可以看作是由若干个子工程(这些子
工程称为“活动” )组成的集合,这些子工程(活动)之间必定存在
一些先后关系,即某些子工程(活动)必须在其它一些子工程(活动)
完成之后才能开始,我们可以用有向图来形象地表示这些子工程(活动)
之间的先后关系,子工程(活动)为顶点,子工程(活动)之间的先后
关系为有向边,这种有向图称为“顶点活动网络”
,又称“AOV网”。
在AOV网中,有向边代表子工程(活动)的先后关系,我们把一
条有向边起点的活动成为终点活动的前驱活动,同理终点的活动称
为起点活动的后继活动。而只有当一个活动全部的前驱全部都完成
之后,这个活动才能进行。例如在上图中,只有当工程1完成之后,
工程2、3、4、5、6才能开始进行。只有当2、3、4全部完成之后,7
才能开始进行。
一个AOV网必定是一个有向无环图,即不应该带有回路。否则,
会出现先后关系的自相矛盾。
上图就是一个出现环产生自相矛盾的情况。4是1的前驱,想完
成1,必须先完成4。3是4的前驱,而2是3的前驱,1又是2的前驱。
最后造成想完成1,必须先完成1本身,这显然出现了矛盾。
板板
板板
int n, m; //结点数和边数
vector<int> G[MAXN]; //存图
int in[MAXN]; // 存储每个结点的入度
//拓扑排序
bool 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 v:G[u]) { //所有邻接点入度减1
in[v]--;
if(in[v]==0) { //入度变为0,则入队
q.push(v);
}
}
}
if(ans.size()==n){ //不存在环,输出序列
for (auto i:ans){
cout<<i<<' ';
}
return true;
}
else{ //存在环
return false;
}
}
例题
家谱树
问题描述
有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。
给出每个人的孩子的信息。
输出一个序列,使得每个人的后辈都比那个人后列出。
输入格式:
第1行一个整数N(1<=N<=100),表示家族的人数。
接下来N行,第I行描述第I个人的儿子。
每行最后是0表示描述完毕。
输出格式:
输出一个序列,使得每个人的后辈都比那个人后列出。
如果有多解输出任意一解。
样例输入:
5
0
4 5 1 0
1 0
5 3 0
3 0
样例输出:
2 4 5 3 1
思路
纯纯板子题
Elaina's code
Elaina's code
#include<bits/stdc++.h>
using namespace std;
#define N 1010
#define ll long long
#define inf 0x3f3f3f3f
#define Elaina 0
int a[N][N],ans[N];
queue <int> q;
int n,m;
void toposort(){
for(int i=1;i<=n;i++){
if(!ans[i]){
q.push(i);
}
}
while(!q.empty()){
int k=q.front();
q.pop();
cout<<k<<" ";
for(int i=1;i<=n;i++){
if(a[k][i]){
ans[i]--;
a[k][i]=0;
if(!ans[i]){
q.push(i);
}
}
}
}
return ;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
while(1){
cin>>m;
if(!m){
break;
}
a[i][m]=1;
ans[m]++;
}
}
toposort();
return Elaina;
}
AC代码
int main(){}
这个真的可以过(在HZOI题库里) 我没骗你
都看到这了,真的不点个赞吗(>ω<*)