hdu 1285 确定比赛名次 (拓扑排序)

来源:互联网 发布:2016融资租赁行业数据 编辑:程序博客网 时间:2024/05/17 01:32


                                                          hdu 1285 确定比赛名次



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 31 22 34 3
 

Sample Output
1 2 4 3
 

     算是特别裸的拓扑排序题了,一个集合之间的关系能够进行拓扑排序,那么他们之间的关系必定不能形成回路.

     拓扑排序:基本的思想是

          1):找到入度为0的点,把这个点和与之相连的点的关系都删除,2)重复之前的步骤


          最后观察是否可以把所有的点全部删完,如果可以,则删除的这些点的顺序即构成了一个拓扑排序.某一个图中,拓扑排序可以有很多个.


        对于本题,我采用邻接表的形式存储点与点之间的先后关系.邻接表的实现一般有三种,1)数组模拟邻接表,2)vector数组,3)链表   一般不用链表.

          代码如下:1)vector数组

#include<stdio.h>#include<string.h>#include<algorithm>#include<string>#include<queue>#include<iostream>using namespace std;int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        vector<int> G[1000];        int a[505];//入度        memset(a,0,sizeof(a));       // int frist[505];        //int next[100000];        int c,d;     //   memset(frist,-1,sizeof(frist));        for(int i=0; i<m; i++)        {            scanf("%d%d",&c,&d);            //查重      //     vector<int>::iterator result=find(G[c].begin(),G[c].end(),d);         //  if(result==G[c].end())          //  {                G[c].push_back(d);                 a[d]++;           // }        }        queue<int> q;LI:        for(int i=1; i<=n; i++)        {            if(a[i]==-1) continue;            if(a[i]==0)            {                q.push(i);                a[i]=-1;                for(int ff=0; ff<G[i].size(); ff++)                    a[G[i][ff]]--;                goto LI;            }        }        while(!q.empty())        {            printf("%d",q.front());            q.pop();            int f=q.front();            if(!q.empty())            printf(" ");        }        printf("\n");    }}


           做这道题以后看了一些别人写的是用二维数组存储关系的,浪费了一半的空间而且需要去重处理,如果有这个关系则赋值为一的话,需要在输入数据的时候进行查重处理,而用邻接表则不必要.因为我即使多输入了,下面的for循环也会给我全部减掉,回到0的状态.下面的代码是关于数组模拟邻接表存图的,如有不理解,可参见:http://blog.csdn.net/stffer/article/details/46382221

          2)数组模拟邻接表:

<strong><span style="font-size:18px;">#include<stdio.h>#include<string.h>#include<algorithm>#include<string>#include<queue>#include<iostream>using namespace std;int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int a[505];//入度        memset(a,0,sizeof(a));        int frist[505];        int next[1000];        int c[550],d[550];        memset(frist,-1,sizeof(frist));        for(int i=0; i<m; i++)        {            scanf("%d%d",&c[i],&d[i]);            next[i]=frist[c[i]];            frist[c[i]]=i;            a[d[i]]++;        }        queue<int> q;LI:        for(int i=1; i<=n; i++)        {            if(a[i]==-1) continue;            if(a[i]==0)            {                q.push(i);                a[i]=-1;                int s=frist[i];                while(s!=-1)                {                    a[d[s]]--;                    s=next[s];                }                goto LI;            }        }        while(!q.empty())        {            printf("%d",q.front());            q.pop();            if(!q.empty())                printf(" ");        }        printf("\n");    }}</span></strong>


0 0
原创粉丝点击