POJ2367

来源:互联网 发布:c语言里 n 编辑:程序博客网 时间:2024/05/22 08:14
/*题意:第一行输入n,代表有n个节点下面有i=1 到 i=n行,代表与第i个节点相连的节点i相当于父亲节点,第i行的数字是i的儿子节点,当第i行输入为0时,停止对该行的输入 将这些节点按辈分从大到小输出 拓扑排序模板题 输入时先用map把各个节点存起来 ,以题目为例 504 5 1 01 05 3 03 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");}} 
原创粉丝点击