• 杭州电子科技大学Online Judge 之 “确定比赛名次(ID1285)”解题报告


    杭州电子科技大学Online Judge 确定比赛名次(ID1285解题报告
    巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo

     

    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

    算法分析: 

    本题是拓扑排序的典型应用。

    因为顶点数量不多,能够採用邻接矩阵来存储图信息,这样算法比較简单,仅仅须要搜索n次,每次把序号最小的入度为0的顶点存储到拓扑序列中即可了。算法思路比較清晰。代码也比較简洁。但时间复杂度和空间复杂度都较高。

    还有一种方法是採用邻接表存储图信息。因为题目要求输出时编号小的队伍在前,所以在入栈时一定要保证先让序号最小的入度为0的顶点在栈顶,这样依据后进先出的特点,能够把序号最小的顶点存储到拓扑序列中。我採用折半插入排序的方法。把入度为0的顶点按递减序排序,然后对图进行深度优先搜索,能获得正确的拓扑序列。

    本算法时间复杂度和空间复杂度都非常好。可是代码较长。

    两种算法都给出代码,大家能够比較一下。并请提出宝贵意见。

    说明: 

    算法思想:拓扑排序,折半插入。

    数据结构:邻接矩阵。邻接表。

    时间复杂度:算法1O(N^2);当中N为顶点数量;

           算法2O(N+M);当中N为顶点数量。M为边的数量

     

    空间复杂度:算法1O(MAXN^2);当中MAXN为最大顶点数量;

    算法2O(MAXN +M);当中MAXN为最大顶点数量;M为边的数量。

    Run ID

    Submit Time

    Judge Status

    Pro.ID

    Exe.Time

    Exe.Memory

    Code Len.

    Language

    Author

     

    12236157

    2014-11-19 14:09:06

    Accepted

    1285

    31MS

    1232K

    1128 B

    C

    巧若拙

    12235820

    2014-11-19 13:07:33

    Accepted

    1285

    15MS

    460K

    4004 B

    C

    巧若拙

     

    代码例如以下:

    算法1

    #include<stdio.h>

    #include<stdlib.h>

     

    #define MAXN 502   //最大顶点数量

     

    int map[MAXN][MAXN] = {0};

     

    void TopoLogicalSort(int n);

     

    int main()

    {

        int i, j, m, n, u, v;

     

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

           {  

               for (i=0; i<MAXN;i++)

                      for (j=0; j<MAXN; j++)

                             map[i][j] = 0;

              

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

                  {

                         scanf("%d%d", &u, &v);

                         if (map[u][v] == 0)    //数据可能会反复

                         {

                                map[u][v] = 1;

                                map[0][v]++; //存储顶点v的入度

                         }

                  }

                 

                  TopoLogicalSort(n);

        }

            

        return 0;

    }

     

    void TopoLogicalSort(int n)

    {

        int i, j, top;

        int topo[MAXN] = {0};

       

        for (top=0; top<n; top++)//总共同拥有n个顶点,搜索n

        {

               for(i=1; i<=n; i++)//寻找入度为0的序号最小的顶点

               {

                      if(map[0][i] == 0)

                      {

                             map[0][i]= -1;

                             break;

                      }

               }

               topo[top]= i;

               for(j=1; j<=n; j++) //弧尾i相应弧头j入度减1

               {

                      if(map[i][j] == 1)

                             map[0][j]--;

               }

        }

       

        for (i=0; i<top-1; i++)

        {

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

        }

        printf("%d ", topo[top-1]);

    }

     

    算法2

    #include<stdio.h>

    #include<stdlib.h>

     

    #define MAXN 510   //最大变量(顶点)数量

     

    typedef int VertexType; //顶点类型由用户自己定义

    typedef int EdgeType; //边上的权值类型由用户自己定义

     

    typedef struct EdgeNode{ //边表结点

        int adjvex; //邻接点域,存储该顶点相应的下标

    //    EdgeType weight; //权值,对于非网图能够不须要

        struct EdgeNode *next; //链域,指向下一个邻接点

    } EdgeNode;

     

    typedef struct VertexNode{ //顶点表结点

        VertexType data; //顶点域,存储顶点信息

        int in;  //存储顶点入度的数量

        EdgeNode *firstEdge; //边表头指针

    } VertexNode;

     

    void CreateGraph(VertexNode*GL, int n, int m);//把顶点和边信息读入到表示图的邻接表中

    int InsertStack(int vec[],int x, int n);//折半插入,递减排序

    voidTopoLogicalSort_DFS(VertexNode *GL, int n);

     

    int main()

    {

        int i, m, n;

        VertexNode GL[MAXN];

       

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

           {  

               CreateGraph(GL, n,m);//把顶点和边信息读入到表示图的邻接表中

              TopoLogicalSort_DFS(GL, n);

        }

            

        return 0;

    }

     

    void CreateGraph(VertexNode*GL, int n, int m)//把顶点和边信息读入到表示图的邻接表中

    {

        int i, u, v;

        EdgeNode *e;

     

        for (i=1; i<=n; i++)//初始化图

        {

            GL[i].data = i;

            GL[i].in = 0;

            GL[i].firstEdge = NULL;

        }

       

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

        {

            e = (EdgeNode*)malloc(sizeof(EdgeNode));//採用头插法插入边表结点

            if (!e)

            {

                puts("Error");

                exit(1);

            }

           

            scanf("%d%d", &u,&v);

            e->next = GL[u].firstEdge;

            GL[u].firstEdge = e;

            e->adjvex = v;

            GL[v].in++;

        }

    }

     

    int InsertStack(int vec[],int x, int n)//折半插入,递减排序

    {

           int low = 0, high = n - 1, mid, j;

     

        while(low <= high) //折半查找插入位置

        {

                  mid = (low + high)/2;

                  if(vec[mid] < x)

                  {

                         high = mid -1;

                  }

                  else

                  {

                         low = mid + 1;

                  }

           }

        //进行插入操作

        for(j=++n; j>low; j--)

        {

            vec[j] = vec[j-1];

        }

        vec[low] = x;

       

        return n;

    }

     

    voidTopoLogicalSort_DFS(VertexNode *GL, int n)

    {

        int i, u, v, top = 0;

        int count = 0;

        EdgeNode *e;

        int topo[MAXN], Stack[MAXN];//有序栈(或优先队列)

       

        for (i=1; i<=n; i++)//将入度为0的顶点按序号大小逆序入栈

        {

            if (GL[i].in == 0)

            {

                 top = InsertStack(Stack, i, top);

            }

        }

        

        while (top > 0)//採用深度优先搜索获取拓扑序列

        {

            u = Stack[--top];

            topo[count++] = u;

           

            for (e=GL[u].firstEdge; e!=NULL;e=e->next)//u的邻接点入度减1,并将入度为0的顶点入栈

            {

                v = e->adjvex;

                if (--GL[v].in == 0)

                {

                       top= InsertStack(Stack, v, top);

                }

            }

        }

       

        for (i=0; i<count-1; i++)

        {

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

        }

        printf("%d ", topo[count-1]);

    }

  • 相关阅读:
    玲珑oj 1129 ST
    HDU 3397 线段树区间修改
    bzoj 1798 双标记区间修改线段树
    HDU 4417 BIT or ST
    HDU 2492 BIT/逆序数/排列组合
    uva 12086 线段树or树状数组练习
    cf 833 A 数论
    wcf的DataContractAttribute与DataMenmberAttribute
    wcf服务查看工具
    git学习-综合性文章
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5203107.html
Copyright © 2020-2023  润新知