生病了好蓝过啊,哎还是家里好,生病都不能码代码了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; }