拓扑排序---(poj 2367)

拓扑排序

 
对一个 有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个 偏序得到该集合上的一个 全序,这个操作称之为拓扑排序。

执行步骤

由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有 出边
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有 回路”信息,否则输出的顶点序列就是一种拓扑 序列
测试数据:第一行表示顶点数和边数;后面的几行是顶点指定另一个顶点(如V1->V2表示1  2 )

6 8

1 2

1 3

1 4

3 2

3 5

4 5

6 4

6 5



#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <stack>
#define NUM 100
using namespace std;


vector<list<int> > Graph(NUM);
int N,M;//表示有n个顶点,m条边
int indegree[NUM];//表示每一个顶点的度;
stack<int> S;

void print(int i)
{
    cout <<"V"<<i<<" ";
}


    //拓扑排序;

void Toposort()
{
    int count = 0;//记录输出顶点的个数
                  //    1、将度为0的入栈
    for(int i = 1;i<=N;i++)
        if(!indegree[i])
            S.push(i);
        //    2、栈不空就输出这个顶点
    while(!S.empty()){
        int temp = S.top();

        cout<<"V"<<S.top()<<" ";
        S.pop();
        count++;


            //        3、一个一个的访问邻接点,获取这个顶点的位置,并让其中相应的邻接的顶点的入度减一;如果为0就入栈;
        for(list<int> :: iterator it =  Graph[temp].begin();it!=Graph[temp].end();it++){
            int k =*it;
            if(!(--indegree[k]))
                S.push(k);
        }
    }
    if(count<N)//判断是否是有环;
        cout <<endl<<"ERROR"<<endl;
    else
        cout <<endl<<"OK"<<endl;
}







int main()
{
    cin>>N;
    cin>>M;
    for(int i  = 1;i<=M;i++){
        int f,e;
        cin>>f>>e;
        if(f!=e){
            Graph[f].push_front(e);
            indegree[e]++;
        }
    }
    for(int i = 1;i<=N;i++){
        cout <<i<<"  ";
        for_each(Graph[i].begin(),Graph[i].end(),print);
        cout <<endl;
    }
    for(int i = 1;i<=N;i++)
        cout <<indegree[i]<<" ";
    cout <<endl;


    Toposort();



    return 0;
}

下面是一个poj是上的相应的习题:
Genealogical tree
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 6185 Accepted: 4079 Special Judge

Description

The system of Martians' blood relations is confusing enough. Actually, Martians bud when they want and where they want. They gather together in different groups, so that a Martian can have one parent as well as ten. Nobody will be surprised by a hundred of children. Martians have got used to this and their style of life seems to them natural. 
And in the Planetary Council the confusing genealogical system leads to some embarrassment. There meet the worthiest of Martians, and therefore in order to offend nobody in all of the discussions it is used first to give the floor to the old Martians, than to the younger ones and only than to the most young childless assessors. However, the maintenance of this order really is not a trivial task. Not always Martian knows all of his parents (and there's nothing to tell about his grandparents!). But if by a mistake first speak a grandson and only than his young appearing great-grandfather, this is a real scandal. 
Your task is to write a program, which would define once and for all, an order that would guarantee that every member of the Council takes the floor earlier than each of his descendants. 

Input

The first line of the standard input contains an only number N, 1 <= N <= 100 — a number of members of the Martian Planetary Council. According to the centuries-old tradition members of the Council are enumerated with the natural numbers from 1 up to N. Further, there are exactly N lines, moreover, the I-th line contains a list of I-th member's children. The list of children is a sequence of serial numbers of children in a arbitrary order separated by spaces. The list of children may be empty. The list (even if it is empty) ends with 0.

Output

The standard output should contain in its only line a sequence of speakers' numbers, separated by spaces. If several sequences satisfy the conditions of the problem, you are to write to the standard output any of them. At least one such sequence always exists.

Sample Input

5
0
4 5 1 0
1 0
5 3 0
3 0

Sample Output

2 4 5 3 1


系谱树
时限:1000MS 内存限制:65536K
提交材料共计: 6172 接受: 4074 特别法官
描述


火星人的血缘关系已经够混乱的了。事实上,火星人在他们想要的地方和他们想要的地方都会萌芽。他们聚集在一起,组成不同的群体,这样火星人就可以有一个父母,也可以有十个。没有人会惊讶于一百的孩子。火星人已经习惯了这一点,他们的生活方式对他们来说似乎是自然的。
在行星理事会中,混乱的家谱系统会导致一些尴尬。那里有火星人的worthiest,因此,为了在所有的讨论中得罪人,首先是给老火星人,而不是年轻的,而且只比最年轻没有孩子的陪审员。然而,维护这个订单确实不是一件简单的任务。火星人不一定都知道他的父母(他的祖父母也没什么可说的!)。但是,如果一个人犯了错误,首先说的是孙子,而不是他年轻时出现的曾祖父,这是一桩真正的丑闻。
你的任务是写一个程序,它将一劳永逸地定义一个命令,保证每一个安理会成员比他的每一个后代都提前发言。
输入


标准输入的第一行包含一个唯一的数字n,1<=n<=100-火星行星理事会的一些成员。根据几百年的传统,理事会成员的自然数是从1到n的自然数。此外,还有确切的n条线,而且,第一行包含了i成员的孩子的列表。儿童的列表是一系列儿童的序列号,它们是由空格分隔的任意顺序。孩子的名单可能是空的。列表(即使是空的)以0结尾。
输出


标准输出应包含在其唯一一行中的一个由空格分隔的扬声器编号序列。如果有几个序列满足问题的条件,则您要将其中任何一个序列写入标准输出。至少有一个这样的序列存在。
样本输入
5
0
4 5 1 0
1 0
5 3 0
3 0
样本输出


2 4 5 3 1

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <stack>
#define NUM 105
using namespace std;

vector<list<int> > Graph(NUM);
int N;
int ingree[NUM];
stack<int> S;

void TuoSort()
{
    int count = 0;
    for(int i = 1;i<=N;i++)
        if(!ingree[i])
            S.push(i);
    while(!S.empty()){
        int temp = S.top();
        cout <<temp<<" ";
        S.pop();
        count++;
        for(list<int> ::iterator it = Graph[temp].begin();it!=Graph[temp].end();it++){
            int k = *it;
            if(!(--ingree[k]))
                S.push(k);
        }
    }
    cout <<endl;
}








int main()
{
    cin>>N;
    for(int i = 1;i<=N;i++){
        for(int j = 1;j<=N;j++){
            int tt;
            cin>>tt;
            if(tt!=0){
                Graph[i].push_back(tt);
                ingree[tt]++;
            }
            else
                break;
        }
        
    }
    TuoSort();
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值