拓扑排序

前几个星期落下的终于要开始一一补上啦~~这个寒假坚持把这本书看完!

机考最后一道题就这么简单,无语,早知道先做这道好了。最简单的拓扑排序应用,判断一个有向图是不是无环的。

标准的拓扑排序代码,《图论与应用》里代码风格不是很喜欢,所以还是觉得这个比较好看一点。

View Code
/*
  (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
  (2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
  (3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.
*/
#include <iostream>
#include <cstring>
using namespace std;

#define Max 100
int ans[Max];
//可以完成拓扑排序则返回True,否则返回false 
bool TopologicalSort(int map[][Max], int n)  //a为邻接矩阵, n为顶点个数 
{
    int into[Max];
    memset(into, 0, sizeof(into));
    memset(ans, 0, sizeof(ans));

    //计算入度 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (map[i][j] > 0)
                into[j]++;
        }
    }

    for (int i = 1; i <= n; i++)
    { 
        int j = 1;

    //寻找入度为0的点,找不到说明拓扑不可能完成 
        while (into[j] != 0)
        {
            j++;
            if (j > n)
                return false;
        }

    //ans依次记录入度为1的点 
        ans[i] = j;
    //删除入度为0的点 
        into[j] = -1;

    //并且删去从该顶点发出的全部有向边. 
        for (int k = 1; k <= n; k++)
        {
            if (map[j][k] > 0)
                into[k]--;
        }
    }
    //输出拓扑排序的情况 
    for (int i = 1; i <= n; i++)
    {
        cout << ans[i] << " ";
    }

    cout << endl;

    return true;
}

 

题目可以见 http://soj.me/show_problem.php?pid=1001&cid=794

View Code
/*
  (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
  (2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
  (3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.

    ps.最简单的拓扑排序应用,判断有环或无环 http://soj.me/show_problem.php?pid=1001&cid=794
*/
#include <iostream>
#include <cstring>
using namespace std;

#define Max 100
int ans[Max];
//可以完成拓扑排序则返回True,否则返回false 
bool TopologicalSort(int map[][Max], int n)  //a为邻接矩阵, n为顶点个数 
{
    int into[Max];
    memset(into, 0, sizeof(into));
    memset(ans, 0, sizeof(ans));

    //计算入度 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (map[i][j] > 0)
                into[j]++;
        }
    }

    for (int i = 1; i <= n; i++)
    { 
        int j = 1;

    //寻找入度为0的点,找不到说明拓扑不可能完成 
        while (into[j] != 0)
        {
            j++;
            if (j > n)
                return false;
        }

    //ans依次记录入度为0的点 
        ans[i] = j;
    //删除入度为0的点 
        into[j] = -1;

    //并且删去从该顶点发出的全部有向边. 
        for (int k = 1; k <= n; k++)
        {
            if (map[j][k] > 0)
                into[k]--;
        }
    }
    //输出拓扑排序的情况 
    for (int i = 1; i <= n; i++)
    {
        cout << ans[i] << " ";
    }

    cout << endl;

    return true;
}

 

posted @ 2013-01-21 13:44  Norcy  阅读(272)  评论(0编辑  收藏  举报