例:对于输入的有向图进行拓扑排序,并输出一个拓扑有序序列;如果存在有向环,则给出提示信息。
首先输入顶点个数n和边数m;然后输入每条边<u,v>,输入0 0结束;顶点序号从1开始记起。
样例输入:
6 8
1 2
1 4
2 6
3 2
3 6
5 1
5 2
5 6
6 8
1 3
1 2
2 5
3 4
4 2
4 6
5 4
5 6
0 0
样例输出:
5 1 4 3 2 6
Network has a cycle!
分析:
样例中第一组测试数据描述的有向图:
样例中第二组测试数据描述的有向图:
存在有向回路的AOV网络。
下面奉上具体实现~
Code:
#include<iostream>
using namespace std;
#define MAX 10 //顶点个数的最大值
struct ArcNode
{
int to;
struct ArcNode *next;
};
int n, m; //顶点个数、边数
ArcNode *List[MAX]; //每个顶点的边链表表头指针
int count[MAX]; //各顶点的入度
char output[100]; //输出内容
void TopSort()
{
int i, top = -1;
ArcNode *temp;
bool bcycle = false; //是否存在有向环的标志
int pos = 0; //写入output数组的位置
for(i = 0; i < n; i++) //入度为0的顶点入栈
{
if(count[i] == 0)
{
count[i] = top;
top = i;
}
}
for(i = 0; i < n; i++)
{
if(top == -1) //栈为空,存在有向回路
{
bcycle = true;
break;
}
else
{
int j = top; top = count[top]; //栈顶顶点j出栈
pos += sprintf(output+pos, "%d ", j+1);
temp = List[j];
//遍历顶点j的边链表,每条出边的终点的入度减1
while(temp != NULL)
{
int k = temp->to;
if(--count[k] == 0)
{
count[k] = top;
top = k;
}
temp = temp->next;
}
}
}
if(bcycle) printf("Network has a cycle!\n");
else
{
output[pos-1] = '\n'; //去掉最后的空格
printf(output);
}
}
int main()
{
int i, u, v; //循环变量、边的起点和终点
while(1)
{
scanf("%d%d", &n, &m); //读入顶点个数、边数
if(n == 0 && m == 0) break;
memset(List, 0, sizeof(List));
memset(count, 0, sizeof(count));
memset(output, 0, sizeof(output));
ArcNode *temp;
for(i = 0; i < m; i++) //边链表
{
scanf("%d%d", &u, &v);
u--; v--;
count[v]++;
temp = new ArcNode;
temp->to = v; temp->next = NULL; //构造邻接表
if(List[u] == NULL) List[u] = temp;
else
{
temp->next = List[u];
List[u] = temp;
}
}
TopSort();
for(i = 0; i < n; i++) //释放边链表上各边结点所占用的存储空间
{
temp = List[i];
while(temp != NULL)
{
List[i] = temp->next;
delete temp;
temp = List[i];
}
}
}
return 0;
}
运行结果:
Ps:如有Bug,欢迎拍砖~