/*题意:第一行输入n,代表有n个节点
下面有i=1 到 i=n行,代表与第i个节点相连的节点
i相当于父亲节点,第i行的数字是i的儿子节点,
当第i行输入为0时,停止对该行的输入
将这些节点按辈分从大到小输出
拓扑排序模板题
输入时先用map把各个节点存起来 ,以题目为例
5
0
4 5 1 0
1 0
5 3 0
3 0
map[2][4] = 1, map[2][5] = 1, map[2][1] = 1; 4, 5, 1 都是以2为父亲节点的
map[3][1] = 1; 1, 的父亲节点是3
map[4][5] = 1, map[4][3] = 1; 3, 5, 的父亲节点是4
map[5][3] = 1; 3, 的父亲节点是5
得到关系图如下
找出没有父亲节点的,例中的2点,再把与以2为父亲节点的边删除,
再找出没有父亲节点的, 此时是4,把节点4删除,并把与4关联的边删除
以此循环,直到没有点为止。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int map[550][550];
int book[550];
int edge[550];
int D[550];
int m,n;
int main()
{
while(~scanf("%d",&n))
{
memset(book, 0, sizeof(book));
memset(map, 0, sizeof(map));
memset(D, 0, sizeof(D));
int u;
int i=1;
while(i<=n)
{
scanf("%d",&u);
if(u==0)
i++;
else
{
if(map[i][u] == 0) //防止有重边
{
map[i][u] = 1; //如果这对父子关系没有记录过就记录下来
D[u]++; //D[u]表示u有几个父亲节点
}
}
}
int t = 0,ans;
while(t < n)
{
for(int i=1; i<=n; i++)
{
if(D[i] == 0 && !book[i]) //如果某个点没有父亲节点,切没有被找到过
{
edge[t++] = i; //将这个点存进去
book[i] = 1; //标记这个点已经找过
ans = i; //为下一步删除与这个点相关联得边准备
break;
}
}
for(int j=1; j<=n; j++)
{
if(map[ans][j] == 1 && !book[j]) //如果上一步找到了ans=i得点,没有父亲节点
{
D[j]--; //遍历1~n ,把与这个点相关联的点的父亲节点数删去1
}
}
}
printf("%d",edge[0]);
for(int i=1; i<t; i++)
printf(" %d",edge[i]); //输出记录的父亲节点
printf("\n");
}
}
POJ2367
最新推荐文章于 2020-07-06 22:23:24 发布