模块化软件开发的基本思想是,将软件整体划分为若干个模块,每个模块分别开发,并各自以接口的方式对外提供模块所能提供的服务。当模块 A 需要调用模块 B 提供的服务时,我们说模块 A 依赖于模块 B。在编译时,只有当模块 B 编译完成后,才能启动模块 A 的编译工作。
现有一个以模块化开发方法开发的软件,其中包含了 N 个软件模块。为了方便起见,我们将这 N个软件模块分别编号 1 ~ N。这 N个软件模块之间共有 M个依赖引用关系,每一个依赖引用关系由一个二元组 (a,b)表示,表示模块 a依赖于模块b 。
现在,请你编写程序,根据这些依赖关系生成这 N个模块的编译顺序。或者报告这N 个模块之间存在递归依赖关系,无法编译。
输入描述
输入第一行包含两个以空格分隔的整数N,M (1<=N<=100 000,0<=M<=100 000) ,表示模块的数量以及依赖关系的数量。
接下来 M行,每行包含两个以空格分隔的整数a,b (a!=b [1,N]) ,表示模块 a依赖于模块 b。
保证输入中的所有依赖二元组 (a,b)两两互不相同。二元组(a,b)与二元组(c.d)相同当且仅当a=c且b=d。
输出描述
如果给定的 N个模块之间存在递归依赖关系导致无法编译,输出一行 RECURSIVE_DEPENDENCY
;否则在一行上输出 N个以空格分隔的整数,表示这 N 个模块的编译顺序。
若存在多个可行的编译顺序,你可以输出任意一个。
样例说明
对于第一组样例,所有可行的编译顺序分别为:
-
3, 4, 2, 1
-
4, 3, 2, 1
扫描二维码关注公众号,回复: 9589556 查看本文章 -
4, 2, 3, 1
对于第二组样例,模块 1 与模块 2 相互引用,形成递归引用,无法编译。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
int main(){
int n,m,i,j,k,p,u;
scanf("%d %d",&n,&m);
int r[m][2],level[n+1],out[n],mom[n],count=0,flag=0;
for(i=1;i<n+1;i++) level[i]=0;
for(i=0;i<m;i++) scanf("%d %d",&r[i][0],&r[i][1]);
for(i=0;i<m;i++) level[r[i][0]]+=1; //该模块有一个前置模块
while(1)
{
flag=0;
for(i=1;i<n+1;i++)
{
if(level[i]==0) //找到没有前置模块的模块
{
out[count]=i;
count++;
level[i]=-1;
mom[flag]=i; //记录本轮找到的祖先
flag++;
}
}
if(flag==0) break; //查询无果
if(count==n) break;
for(j=0;j<m;j++)
{
if(level[r[j][1]]==-1)
{
level[r[j][0]]-=1; //取消该模块对于其它模块的前置关系
}
}
for(p=0;p<flag;p++)
{
level[mom[p]]=-2; //移走本轮找到的祖先
}
}
if(count==n)
{
for(k=0;k<n-1;k++)
{
printf("%d",out[k]);
printf(" ");
}
printf("%d\n",out[n-1]);
}
else printf("RECURSIVE_DEPENDENCY\n");
}