数据结构实验之图论十:判断给定图是否存在合法拓扑序列
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。
Input
输入包含多组,每组格式如下。
第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)
后面m行每行两个整数a b,表示从a到b有一条有向边。
Output
若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。
Sample Input
1 0 2 2 1 2 2 1
Sample Output
YES NO
http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/2720/pid/2140
拓扑序列,即有向图无环。
每次找一个入度为零的点,将所有和它相连的点的入度减一(删除相连的边),重复此步骤(有n个点,每次选择一个入度为0的点,进行n次)。如果这时还有入度不为零的点,证明有环,输出NO,反之输出YES。
#include<stdio.h>
#include<string.h>
int map[20][20],flag[20],du[20];//边,每个节点是否已被删去,每个节点的入度
int main()
{
int i,j,m,n,v,u,num,k;
while(scanf("%d %d",&n, &m)!= EOF)//n个点,m条边
{
memset(map,0,sizeof(map));
memset(du,0,sizeof(du));
memset(flag,0,sizeof(flag));
if(m == 0)//边的个数为0,一定是拓扑序列
{
printf("YES\n");
continue;
}
for(i = 0; i < m; i ++)
{
scanf("%d %d",&u, &v);
map[u][v] = 1;
du[v] ++;//此边的入度+1
}
num = 0;
for(i = 1; i <= n; i ++)//总共要删n个点,循环n次
{
for(j = 1; j <= n; j ++)
{
if(!du[j]&&!flag[j])//如果此点没有被删除,而且入度为0
{
flag[j] = 1;//删除此点
for(k = 1; k <= n; k ++)//并把此点指向的其他点的入度减一
{
if(map[j][k])
du[k] --;
}
num ++;//个数+1
break;//跳出此循环,进行大循环,找下一个入度为0得点
}
}
}
if(num == n)//如果成功删掉了n个点,那就是拓扑序列
printf("YES\n");
else
printf("NO\n");
}
return 0;
}