拓扑排序:在图论中,由一个有向非循环图(DAG)的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(Topological sorting)。
1.每个顶点出现且只出现一次;
2.若A在序列中排在B的前面,则在图中不存在从B到A的路径。
1.每个顶点出现且只出现一次;
2.若A在序列中排在B的前面,则在图中不存在从B到A的路径。
也可以定义为:拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面。
实现过程:
1.读入图,建一个记录顶点入度的数组,记录每个顶点的入度
2.建一个队列,记录入度为0的顶点
3.从队列中出来一个顶点u,遍历所有顶点,若u,v有边相连,则将所连的边标记为已删除(即令g[u][v]=0),并对顶点v的入度减1,若顶点v的入度为0,入队;
4.若队空则退出,否则重复步骤4;
完成上述过程后,若所有顶点的度都为0,则说明该图是一个有向无回路图,否则为有回路
HDU 3342(Legal or Not)
题意:有n个人,m个关系,若A是B的师父,而B又是A的师父则说明这种关系不合法,判断这n个人中的关系合不合法;
思路:只需判断有无回路;
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int SIZE = 200;
int g[SIZE][SIZE], de[SIZE];
int TopoSort(int n){
queue<int> p;
for(int i = 0;i < n;i++)
if(de[i] == 0)
p.push(i);
while(!p.empty()){
int r = p.front();
p.pop();
for(int i = 0;i < n;i++)
if(g[r][i]){
de[i]--;
g[r][i] = 0;
if(!de[i])
p.push(i);
}
}
for(int i = 0;i < n;i++)
if(de[i] > 0)
return 0;
return 1;
}
int main(){
int n, m;
while(scanf("%d%d", &n, &m)){
int i, j, a, b;
memset(de, 0, sizeof(de));
memset(g, 0, sizeof(g));
if(n == 0&&m == 0)
break;
for(i = 0;i < m;i++){
scanf("%d%d", &a, &b);
if(g[b][a] == 1)
continue;
g[b][a] = 1;
de[a]++;
}
if(TopoSort(n))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}