POJ2367 - Genealogical tree - 拓扑排序模板题
题意
第一行一个5,代表1-5五个元素,每一行以0结束说明该行输入结束,往下走,第一行代表1的儿子没有,第二行代表2的儿子是4、5、1,第三行代表3的儿子是1,第四行代表4的儿子是5、3,第五行代表5的儿子是3;从长辈到晚辈依次输出。
思路
拓扑排序模板题。这一题英文看不懂,翻译了发现我,,中文也看不懂,还是别人和我讲的题意。之前已经看过拓扑排序,这也是这一周新学的知识点,做了一道简单入门的拓扑题。但是在昨天周赛上,不仅没写出来,而且数组开的也有问题,思路是没错,但是代码实现的过程偏了很多,希望多多反思自己学习效率上的问题以及思维逻辑方式上的问题。
AC代码
#include<stdio.h>
#include<string.h>
//需要开三个数组
int a;//输入
int dis[110][110];//标记相关的
int r[110];//每一个元素的入度
int ans[110];//存最后输入的答案
int main()
{
int n,i,j;
while(~scanf("%d",&n))//n行,n个元素
{
// memset(a,0,sizeof(a));
memset(dis,0,sizeof(dis));
memset(r,0,sizeof(r));
memset(r,0,sizeof(r));
for(i=1;i<=n;i++)//控制行数
{
for(j=1;;j++)
{
// scanf("%d",&a[j]);
scanf("%d",&a);
if(a==0)
break;
if(dis[i][a]==0)//如果这条边之前没有联系
{
dis[i][a]=1;//建立联系
r[a]++;//入度++,有了联系之后才将后面对应的点入度++
}
}
}
int b;//用来记录结点
int k=0;
for(i=1;i<=n;i++)//n行
{
for(j=1;j<=n;j++)
{
if(r[j]==0)//如果入度为0
{
r[j]--;//入度--,让它入度为负数
ans[k++]=j;//存入结果中
b=j;//记录结点
break;
}
}
//找到入度为0的数之后,再找和它相关的边删除
//并且和它相关的那条边对应的元素入度--
for(j=1;j<=n;j++)//通过循环找到所有相关的边
{
if(dis[b][j]==1)//找到对应的边
{
dis[b][j]=0;
r[j]--;
}
}
}
for(i=0;i<k-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[k-1]);
}
return 0;
}