您的位置:首页 > 其它

杭电1285拓扑排序解题报告

2013-05-30 10:49 323 查看

http://acm.hdu.edu.cn/showproblem.php?pid=1285

确定比赛名次


Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K
(Java/Others)

Total Submission(s): 4953 Accepted Submission(s):
1832


Problem Description
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。



Input
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。



Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。



Sample Input
4 3 1 2 2 3
4 3



Sample Output
1 2 4
3



Author
SmallBeer(CML)



Source
杭电ACM集训队训练赛(VII)



Recommend
lcy
简单的拓扑排序但是我很水所以做了好久啊。。现在还是没什么掌握。。acm不是那么容易的。。加油吧。
#include<stdio.h>

#include<string.h>

int arc[501][501]; //邻接矩阵

int n,m,top;

int vis[501]; //标记访问过了没

int index[501];//标记入度

void init()

{

int i;

int a,b;


memset(vis,0,sizeof(vis));

memset(index,0,sizeof(index));

memset(arc,0,sizeof(arc));


for(i=1;i<=m;i++)


{


scanf("%d %d",&a,&b);


if(!arc[a])// 因为有可能出现重边,所以前面初始为0


{

arc[a][b]=1;


index[b]++; //b的入度加1因为a是大于b的即a指向b从a到b(b是弧尾);


}


}

}

void topsort()

{

int
i,j;


while(top<n)


{

for(i=1;i<=n;i++)


if(index[i]==0&&!vis[i])
//每一次都可以找到入度为0的点


break; //入度为0,并且i最小,一定可以排在最前面


vis[i]=1;

if(top)
//设置一个top是为了控制数据之间的空格;(第一个数据前面没有多余的空格,最后一个数据之后也没有多余的空格)

printf("
");

printf("%d",i);

top++;

for(j=1;j<=n;j++)

{

if(arc[i][j])

index[j]--;//把以i为起点j为终点的入度减1

}

}

}

int main()

{


while(scanf("%d%d",&n,&m)!=EOF)

{


init(); //调用函数进行数据的输入以及初始化数组;


top=0;//设置一个top是为了控制数据之间的空格;(第一个数据前面没有多余的空格,最后一个数据之后也没有多余的空格)

topsort();//调用函数进行拓扑排序;


printf("\n");//调用结束后有一个空行哦

}

return
0;

}



有重新写了下,感悟挺多的(参考别人的)。。2012.7.23

#include<stdio.h>

#include<string.h>

[b]int
map[502][502],indegree[502],n,m,pur[502];

void
topsort()

{



int
i,j,k=1;


for
(i=1;i<=n;i++)


{



for
(j=1;j<=n;j++)


{



if
(indegree[j]==0)//当入度为0时

{



indegree[j]--;//入度-1

pur[k++]=j;//

for
(int x=1;x<=n;x++)


{



if
(map[j][x])//以该顶点为弧尾的度数-1


indegree[x]--;


}



break
;//这个还不能少,当把该顶点的相关弧尾的入度-1全部处理完后要进行下一个

}






}

}

}


int
main()

{



int
i;


while
(scanf("%d
%d",&n,&m)!=EOF)//输入n,m(n表示队伍的个数,m表示接着有m行的输入数据)

{



memset(map,0,sizeof(map));//清零

memset(indegree,0,sizeof(indegree));


int
a,b;


for
(i=1;i<=m;i++)//m表示接着有m行的输入数据

{



scanf("%d
%d",&a,&b);


if
(!map[a][b])//一开始都是没有访问过的[memset(map,0,sizeof(map));//清零]

{



map[a][b]=1;//标记访问过了

indegree[b]++;//弧尾(b)入度+1

}


}



topsort();//进行拓扑排序

for
(i=1;i<=n;i++)


{



if
(i!=n)//最后一个数的后面没有空格

printf("%d
",pur[i]);


else



printf("%d\n",pur[i]);


}


}



return
0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: