标签:== ret 存在 cst 输出 code 输入 输入数据 ica
求1到n的其中一种拓扑序,保证存在一种拓扑序。输入格式是:第一行读入n,接下来n行,第i+1行表示有由i指向其他点的边,以0结尾。(直接一个0就是它没有连向任何点)。
5
0
4 5 1 0
1 0
5 3 0
3 0
2 4 5 3 1
我们先输入数据,再输入的时候用一个数组num_indegree[i]来记录结点i的入度(即进入这个结点的数量)。之后我们再找所有结点中入度为0的结点把它压入一个栈node中。之后我们开始把栈中的结点弹出并输出,并把这个弹出的结点所到的结点的入度减一,如果某个结点在这样之后入度变为0了,那么意味着这个结点没有前驱了,就把这个结点压人栈。这样不断循环直到出现两种情况:
栈弹完了后没有边剩余,那么这样我们就拓补排序结束
如果栈弹完了仍有结点没有排完,那么这样就说明这个图中有环 ( ps:这个我没有试验过,正确性未知 )
#include <iostream>
#include <stack>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e2+5;
int n,k;
int num_indegree[N];
stack <int> node; //存入度(即每个点进来的边)为0的点
vector <int> graph[N];
void add(int x,int y){
graph[x].push_back(y);
}
void toposort(){
while(!node.empty()){ //如果栈非空
int u=node.top();
printf("%d ",u);
node.pop();
vector <int> :: iterator it;
for(it=graph[u].begin();it!=graph[u].end();it++){
num_indegree[*it]--;
if(num_indegree[*it]==0) node.push(*it);
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int k;
while(true){
scanf("%d",&k);
if(k==0) break;
add(i,k);
num_indegree[k]++; //计算每个点的入度
}
}
for(int i=1;i<=n;i++){
if(num_indegree[i]==0){ //如果找到一个没有前驱的点
node.push(i); //把入度为0的点进栈
}
}
toposort();
return 0;
}
标签:== ret 存在 cst 输出 code 输入 输入数据 ica
原文地址:https://www.cnblogs.com/lixiao189/p/9300968.html