拓扑排序是为了解决活动的先后问题,在满足拓扑排序的图中,任意一对结点<u,v>,总可以找到它们的顺序关系,例如u在v前,可能是直接,也可能是间接,思想就是建立一个有向无环图DAG,这样就可以满足结点的关系只有一种。
题目:若A是B的老师,则B是A的学生,但是不能出现环,即A是B的老师,B是C的老师,C又是A的老师;甚至A和B互为老师也是不允许的。要求给出N个人,M个关系<x,y>表示x是y的老师,而y是x的学生,判断是否为有向无环图。
思想是首先初始化各结点,按照输入的边,确定各结点的入度,当一个结点的入度为0时加入队列,每次从队列队首出队一个元素,将该结点所指向的结点的入度减1,若有结点因此入度减为0,则加入队列,直到所有的结点都经过队列弹出,即为有向无环图,否则不是有向无环图。
代码为:
#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#define N 1001
using namespace std;
vector<int> edge[N];
queue<int> Q;
int inDegree[N];
int main()
{
int n,m;
while(scanf("%d%d", &n, &m) != EOF)
{
if(n == 0 && m == 0)
break;
for(int i = 0; i < n; i++)//编号从0开始
{
inDegree[i] = 0;
edge[i].clear();
}
while(!Q.empty())
Q.pop();
while(m-- != 0)
{
int a, b;
scanf("%d%d", &a, &b);
edge[a].push_back(b);
inDegree[b]++;
}
for(int i = 0; i < n; i++)
{
if(inDegree[i] == 0)
{
Q.push(i);
}
}
int cnt = 0;//记录已经加入到拓扑序列的结点
while(!Q.empty())
{
int nowP = Q.front();
Q.pop();
cnt++;//每次出队一个元素,拓扑网络中的结点数就加1
for(int i = 0; i < edge[nowP].size(); i++)
{
inDegree[edge[nowP][i]]--;//vector中的元素下标从0开始
if(inDegree[edge[nowP][i]] == 0)
{
Q.push(edge[nowP][i]);
}
}
}
if(cnt == n)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
运行结果: