首页 > 代码库 > PTA Topological Sort

PTA Topological Sort

生病了好蓝过啊,哎还是家里好,生病都不能码代码了TAT……

下面是题目:

Write a program to find the topological order in a digraph.

Format of functions:

bool TopSort( LGraph Graph, Vertex TopOrder[] );

where LGraph is defined as the following:

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{
    Vertex AdjV;
    PtrToAdjVNode Next;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];

typedef struct GNode *PtrToGNode;
struct GNode{  
    int Nv;
    int Ne;
    AdjList G;
};
typedef PtrToGNode LGraph;

The topological order is supposed to be stored in TopOrder[] where TopOrder[i]is the i-th vertex in the resulting sequence. The topological sort cannot be successful if there is a cycle in the graph -- in that case TopSort must returnfalse; otherwise return true.

Notice that the topological order might not be unique, but the judge‘s input guarantees the uniqueness of the result.

Sample program of judge:

#include <stdio.h>
#include <stdlib.h>

typedef enum {false, true} bool;
#define MaxVertexNum 10  /* maximum number of vertices */
typedef int Vertex;      /* vertices are numbered from 0 to MaxVertexNum-1 */

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{
    Vertex AdjV;
    PtrToAdjVNode Next;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];

typedef struct GNode *PtrToGNode;
struct GNode{  
    int Nv;
    int Ne;
    AdjList G;
};
typedef PtrToGNode LGraph;

LGraph ReadG(); /* details omitted */

bool TopSort( LGraph Graph, Vertex TopOrder[] );

int main()
{
    int i;
    Vertex TopOrder[MaxVertexNum];
    LGraph G = ReadG();

    if ( TopSort(G, TopOrder)==true )
        for ( i=0; i<G->Nv; i++ )
            printf("%d ", TopOrder[i]);
    else
        printf("ERROR");
    printf("\n");

    return 0;
}

/* Your function will be put here */

Sample Input 1 (for the graph shown in the figure):

技术分享

5 7
1 0
4 3
2 1
2 0
3 2
4 1
4 2

Sample Output 1:

4 3 2 1 0

Sample Input 2 (for the graph shown in the figure):

技术分享

5 8
0 3
1 0
4 3
2 1
2 0
3 2
4 1
4 2

Sample Output 2:

ERROR

解答:

这道题目蛮基础的……就是把拓扑排序实现一遍,先遍历整个图计算所有节点的入度并存入数组inorder中,然后进行一个循环,循环每次找到任意一个入度为0的点加入拓扑排序的那个数组中,再将所有从该节点出发的边删除。当然这里在寻找入度为0的节点的时候可以用队列进行一个优化(毕竟每次找入度为0的节点都要遍历inorder数组太费时了),不然第三个测试点会超时(本宝宝还专门试了一下),就是一开始先遍历一遍inorder将入度为0的点入队,然后之后每次删除边的时候都判断一下是否会产生入度为0的点,如果是的话就将它入队,而每次取入度为0的节点加入拓扑排序的数组中的时候就只要取队首节点就可以了,相当于出队操作。这样优化后判断是否有环就可以这样进行:如果在将所有节点加入拓扑排序之前队列就为空了,那么就表示该图有环。

//
//  main.c
//  Topological Sort
//
//  Created by 余南龙 on 2016/11/16.
//  Copyright ? 2016年 余南龙. All rights reserved.
//

bool TopSort( LGraph Graph, Vertex TopOrder[] ){
    int indegree[Graph->Nv];
    int Q[MaxVertexNum];
    int i, head = -1, tail = 0, j = 0;
    PtrToAdjVNode tmp;
    
    for(i = 0; i < Graph->Nv; i++){
        indegree[i] = 0;
    }
    for(i = 0; i < Graph->Nv; i++){
        tmp = (Graph->G[i]).FirstEdge;
        while(NULL != tmp){
            indegree[tmp->AdjV]++;
            tmp = tmp->Next;
        }
    }
    for(i = 0; i < Graph->Nv; i++){
        if(0 == indegree[i]){
            Q[tail] = i;
            tail++;
        }
    }
    for(i = 0; i < Graph->Nv; i++){
        if(0 == tail){
            return false;
        }
        if(head == tail - 1){
            return false;
        }
        
        TopOrder[j++] = Q[++head];
        tmp = (Graph->G[Q[head]]).FirstEdge;
        while(NULL != tmp){
            indegree[tmp->AdjV]--;
            if(0 == indegree[tmp->AdjV]){
                Q[tail] = tmp->AdjV;
                tail++;
            }
            tmp = tmp->Next;
        }
    }

    return true;
}

 

PTA Topological Sort