码迷,mamicode.com
首页 > 编程语言 > 详细

拓补排序

时间:2018-07-12 20:07:45      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:==   ret   存在   cst   输出   code   输入   输入数据   ica   

模板题目:

题目来源

[POJ] Genealogical tree

题目描述:

求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了,那么意味着这个结点没有前驱了,就把这个结点压人栈。这样不断循环直到出现两种情况:

  1. 栈弹完了后没有边剩余,那么这样我们就拓补排序结束

  2. 如果栈弹完了仍有结点没有排完,那么这样就说明这个图中有环 ( 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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!