hdu 1285 拓扑排序

http://acm.hdu.edu.cn/showproblem.php?pid=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 3 1 2 2 3 4 3
 

Sample Output
   
   
   
   
1 2 4 3
拓扑排序是对有向无环图来说的,无向图和有环的有向图是没有拓扑排序的。对一个有向无环图G进行拓扑排序是将G中的所有点排成一个线性序列,使得图中任意一个有向无环图中任意一个顶点u和v若图中存在边<u,v>,则u在线性序列中出现在v之前。对有向图进行拓扑排序产生的线性序列称为满足拓扑排序次序的序列,简称拓扑排序。一个有向无环图通常可以 表示某种动作序列或方案,而有向无环图的拓扑序列通常表示为某种方案切实可行。
基本算法:

(1)从有向图中选择一个没有前驱(即入度为零)的顶点并且输出它。

(2)从网中删除该顶点,并且删除从该顶点发出的全部有向边。

(3)重复上述两步,直到剩余的网中不再存在没有前驱的顶点为止。

对于上面的算法,如果最终存在不能剩余的点,则剩余的点和期间的边一定构成环路,否则的话,算法结束时,图G的点都会别删除并输出。

利用邻接矩阵的实现:

#include <string.h>
#include <stdio.h>
#include <iostream>
#define  N 550
#define  M 2100
using namespace std;
int map[N][N],in[M],f[M];
int main()
{
    int i,j,t,m,n,a,b,num;
    while(~scanf("%d %d",&n,&m))
    {
        memset(map,0,sizeof(map));
        memset(in,0,sizeof(in));
        while(m--)
        {
            scanf("%d %d",&a,&b);
            if(map[a][b]==0)
            {
                map[a][b]=1;
                in[b]++;
            }
        }
        num=0;
        while(num!=n)
        {
            for(i=1;i<=n;i++)
                if(in[i]==0)
                {
                    in[i]=-1;
                    f[num++]=i;
                    t=i;
                    break;
                }
            for(j=1;j<=n;j++)
            {
                if(map[t][j]==1)
                {
                    in[j]--;
                }
            }
        }
        for(i=0;i<n;i++)
            printf(i==n-1?"%d\n":"%d ",f[i]);
    }
    return 0;
}

利用链式前向星的实现:

#include <string.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int head[10005],ip,indegree[10005],queue[10005];
struct note
{
    int to;
    int next;
};
note edge[10005];
void add(int u,int v)
{
    edge[ip].to=v,edge[ip].next=head[u],head[u]=ip++;
}
int main()
{
    int m,n,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        memset(head,-1,sizeof(head));
        memset(indegree,0,sizeof(indegree));
        ip=0;
        for(int i=0; i<m; i++)
        {
            cin >> a >>b;
            add(a,b);
            indegree[b]++;
        }
        int c=0;
        while(c<n)
        {
            for(int i=1; i<=n; i++)
            {
                if(0==indegree[i])
                {
                    queue[c++]=i;
                    indegree[i]=-1;
                    for(int j=head[i]; j!=-1; j=edge[j].next)
                        indegree[edge[j].to]--;
                    break;
                }
            }
        }
        for(int i=0; i<c; i++)
            printf(i==c-1?"%d\n":"%d ",queue[i]);
    }
    return 0;
}


你可能感兴趣的:(hdu 1285 拓扑排序)