拓扑排序知识点
1、拓扑排序就是想让图中的全部有向边都从左指向右,同时将所有顶点都排列在同一条水平线上。对于所有有向边(u,v)均有u比v先出现。
2、用深度优先和广度优先均可以实现拓扑排序
3、拓扑排序能够判断是否存在环
4、有向无环图常常用来表示事件之间的驱动与依赖关系
拓扑排序理解
有一个图,每次找到入度为零的点,把它删掉
并且把它指向的那些顶点的入度减一,
如果有环肯定会被删到剩一个环而导致找不到入度为零的点(因为循环执行n次,每次只删一个顶点)
如果没有环那肯定执行n次后刚好删完。
题目
http://acm.hdu.edu.cn/showproblem.php?pid=3342
HDU 3342 拓扑排序
代码
题目说给你顶点的个数,然后给出m个边的关系(存在/不存在),根据这些信息判断图中是否存在环。
有环输出NO,没有就输出YES。
#include <cstdio>
#include <cstring>
typedef long long ll;
using namespace std;
const int INF=0x3f3f3f3f;
//对于有向无环图,进行拓扑排序有两种实现方法,一种是入度表,一种是DFS,时间复杂度均为O(V+E)
int mp[105][105];
int indegree[105];
int n,m;
int main()
{
while(scanf("%d%d",&n,&m)&&n)//n个顶点,m条边
{
memset(mp,0,sizeof(mp));
memset(indegree,0,sizeof(indegree));
int a,b;
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
if(!mp[a][b])
{
mp[a][b]=1;//存在关系
indegree[b]++;//入度加一
}
}
int flag=1,i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)//寻找看是否有入度为零的顶点
{
if(indegree[j]==0)//发现入度为零的点
{
indegree[j]--;
for(int k=0;k<n;k++)//把它指向的顶点的入度都减一
if(mp[j][k])//mp[j][k]即为由j指向k的关系是否存在,存在就把入度减一
indegree[k]--;
break;//找到就跳出 ,做到一次只删一个入度为零的点
}
}
if(j==n)//说明找不到入度为零的,说明有环
{
flag=0;
break;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}