【算法小总结】拓扑排序+例题解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介:

题目1449:确定比赛名次
时间限制:1 秒内存限制:128 兆特殊判题:否提交:669解决:293
题目描述:
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
输入:
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
输出:
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
样例输入:
4 3
1 2
2 3
4 3
样例输出:
1 2 4 3

 


//拓扑排序
/*拓扑排序方法如下:
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.*/

#include<stdio.h>
#include<string.h>
int degree[510],bin[510],map[510][510];
void ToPu(int n)
{
   int i,j,p;
   for(i=1;i<=n;i++)
   {
      p=-1;//用来记录入度为0的结点 
      for(j=1;j<=n;j++)
      {
         if(degree[j]==0)//如果入度为0 
         {
           degree[j]--;//让他为负数
           bin[i]=p=j;
           break;//找到那个入度为0的结点,说明他是本组查找的元老 
         } 
      }
      for(j=1;j<=n;j++)
      {
        if(map[p][j]==1)//去掉p链接的所有路 
        {
           map[p][j]=0;
           degree[j]--;//j的入度减去1 
        } 
      }
   }    
}
int main()
{
    int i,j,n,m,x,y;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
       memset(degree,0,sizeof(degree));
       memset(bin,0,sizeof(bin));
       memset(map,0,sizeof(map));
       for(i=0;i<m;i++)    
       {
           scanf("%d %d",&x,&y);
           if(map[x][y]==0)  
           {
              map[x][y]=1;
              degree[y]++;//y点的入度加一 
           }              
       } 
       ToPu(n);   
       printf("%d",bin[1]);
       for(i=2;i<=n;i++)
       printf(" %d",bin[i]);
       puts("");     
    }
    return 0;
}


 

因为每次都要搜索入度为0的节点,花费的时间是O(n^2)

可以进行优化到O(E+V)

优化思想,可以通过将所有(未分配拓扑编号)入度为0的顶点放在一个特殊的盒子中而避免
这种无效的劳动。当降低邻接顶点的入度的时候,检查每一个顶点并在他入度为0的时候把它放入盒子。

步骤:
1.对每一个顶点计算它的入度,将所有入度为0的顶点放入一个初始为空的队列中。
2.当队列不空时,删除一个顶点v,并将与v邻接的所有的顶点的入度减1。
3.在刚刚的操作中,只要有一个顶点的入度降为0,就把该顶点放入队列中。
此时,拓扑排序就是顶点出队的顺序。

优化代码:
//注意,这个写法是没要求输出时编号小的队伍在前
//写这个的目的是清楚优化的方法,不是为此题而编写

void ToPu(int n)
{
   queue<int> q;  
   int sum=1;
   int v,i;
   
   while(!q.empty()){q.pop();}
   for(i=1;i<=n;i++)
   if(degree[i]==0)
      q.push(i);
      
   while(!q.empty())
   {
      v=q.front();
      q.pop();
      bin[sum++]=v;
      for(i=1;i<=n;i++)
      {
         if(map[v][i]==1)
         {
            degree[i]--;
            if(degree[i]==0)
               q.push(i);
         }
      }
   }
}


 

相关文章
|
18天前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
37 0
|
11天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
30 3
|
13天前
|
搜索推荐 算法
插入排序算法的平均时间复杂度解析
【10月更文挑战第12天】 插入排序是一种简单直观的排序算法,通过不断将未排序元素插入到已排序部分的合适位置来完成排序。其平均时间复杂度为$O(n^2)$,适用于小规模或部分有序的数据。尽管效率不高,但在特定场景下仍具优势。
|
13天前
|
前端开发 算法 JavaScript
无界SaaS模式深度解析:算力算法、链接力、数据确权制度
私域电商的无界SaaS模式涉及后端开发、前端开发、数据库设计、API接口、区块链技术、支付和身份验证系统等多个技术领域。本文通过简化框架和示例代码,指导如何将核心功能转化为技术实现,涵盖用户管理、企业店铺管理、数据流量管理等关键环节。
|
18天前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
28 0
|
19天前
|
机器学习/深度学习 算法 PyTorch
Pytorch-SGD算法解析
SGD(随机梯度下降)是机器学习中常用的优化算法,特别适用于大数据集和在线学习。与批量梯度下降不同,SGD每次仅使用一个样本来更新模型参数,提高了训练效率。本文介绍了SGD的基本步骤、Python实现及PyTorch中的应用示例。
25 0
|
18天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
39 0
|
18天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
29 0
|
18天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
32 0
|
18天前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
44 0

推荐镜像

更多