`
128kj
  • 浏览: 604155 次
  • 来自: ...
社区版块
存档分类
最新评论

拓扑排序入门练习

    博客分类:
阅读更多
   拓扑排序简单来说就是把一个图的所有节点排序,使得每一条有向边(u,v)对应的u都排在v的前面。 拓扑排序最大的用途就是判断一个有向图是否有环。

无前趋的顶点优先的拓扑排序方法

    该方法的每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:
    NonPreFirstTopSort(G){//优先输出无前趋的顶点
      while(图G中有人度为0的顶点)do{
       从G中选择一个人度为0的顶点v且输出之;
       从G中删去v及其所有出边;
       }
      if(输出的顶点数目<|V(G)|)
        //若此条件不成立,则表示所有顶点均已输出,排序成功。
        Error("G中存在有向环,排序失败!");
     }

性质
1、 拓扑排序在有向无环图中才能排出有效的序列,否则能判断该有向图有环。
2、如果输入的有向图中的点,不存在入度为0的点,则该有向图存在回路
3、如果存在的入度为0的点大于一个,则该有向图肯定不存在一个可以确定的拓扑序列但并不妨碍拓扑排序

例: 有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

典型的拓扑排序算法
import java.util.*;

方法一:(邻接矩阵实现图存储)
public class Main {

	private  int n, m;
	private int[] indegree;// 顶点的入度
	private int[] result;// 保存最后排好序的结果
	private int[][] G;// 邻接矩阵存储
	private  Queue<Integer> que;//存入入度为0的顶点

        public Main(int n,int m,int[] indegree,int[][] G){
             this.n=n;
             this.m=m;
             this.indegree=indegree;
             this.G=G;
        }
             
       

	public static void main(String[] args) {
	  Scanner sc = new Scanner(System.in);
           int[][] G;
           int[] indegree;
           int n,m;
	    while (sc.hasNext()) {
	      n = sc.nextInt();
	      m = sc.nextInt();
	      G = new int[n + 1][n + 1];
	      indegree = new int[n + 1];

                 while (m-- > 0) {
		   int u = sc.nextInt();
		   int v = sc.nextInt();
              if (G[u][v] == 0) {// 这个条件一定要,避免重边的情况比如a b可能出现两次的情况
		     indegree[v]++;
		     G[u][v] = 1;
		    }
		 }
                 Main ma=new Main(n,m,indegree,G);
			ma.topsort();
			
		}
	}

	private  void topsort() {
          result = new int[n + 1];
          que = new PriorityQueue<Integer>();//同名次时,序号小的排前,所以用优先队列
	  int index = 0;
	  for (int i = 1; i <= n; i++) {//找出图中所有入度为O的顶点
	    if (indegree[i] == 0)
		que.add(i);//编号小的在前
	  }
	  while (!que.isEmpty()) {
	     int u = que.poll();
	     result[++index] = u;
             for (int i = 1; i <= n; i++) {
                if (G[u][i] == 1) {
		  indegree[i]--;//模拟删除顶点,i的入度减1
		  if (indegree[i] == 0)
		    que.add(i);
		}
	     }
	  }
          // 输出
	   System.out.print(result[1]);
	   for (int i = 2; i <= n; i++) {
		System.out.print(" "+result[i]);
	   }
	   System.out.println();
	}

  }

import java.util.*;

方法二:拓扑排序(使用邻接表实现)
public class Main{
	private int n, m;
	private int[] indegree;// 顶点的入度
	private int[] result;// 保存最后排好序的结果
	private List<ArrayList<Integer>> G;// 邻接表。
	private Queue<Integer> que;

        public Main(int n,int m,int[] indegree,List<ArrayList<Integer>> G){
             this.n=n;
             this.m=m;
             this.indegree=indegree;
             this.G=G;
        }

	public static void main(String[] args) {
          int n,m;
          int[] indegree;
          List<ArrayList<Integer>> G;
          Scanner sc = new Scanner(System.in);
	  while (sc.hasNext()) {
	    n = sc.nextInt();
	    m = sc.nextInt();
	    G = new ArrayList<ArrayList<Integer>>();
	    for(int i = 1;i<=n+1;i++)
               G.add(new ArrayList<Integer>());//初始化邻接表
	    indegree = new int[n + 1];
            while (m-- > 0) {
              int u = sc.nextInt();
              int v = sc.nextInt();
        if (!G.get(u).contains(v)) {// 这个条件一定要,避免重边的情况比如a b可能出现两次的情况
                 indegree[v]++;
                 G.get(u).add(v);
               }
	    }
             Main ma=new Main(n,m,indegree,G);
             ma.topsort();
           }
        }
			
	

	private  void topsort() {
          result = new int[n + 1];
          que = new PriorityQueue<Integer>();
	  int index = 0;
	  for (int i = 1; i <= n; i++) {
	     if (indegree[i] == 0)
		que.add(i);
	   }
           while (!que.isEmpty()) {
	     int v = que.poll();
	     result[++index] = v;
	     for (int i : G.get(v)) {
                 indegree[i]--;
                 if (indegree[i] == 0)
                   que.add(i);
             }
           }
          // 输出
         System.out.print(result[1]);
         for (int i = 2; i <= n; i++) {
            System.out.print(" " + result[i]);
         }
         System.out.println();
       }
 }



0
0
分享到:
评论

相关推荐

    程序员的数学4:图论入门.pptx

    拓扑排序则是在有向无环图(DAG)中对节点进行排序,使得对于图中任何一条边(u, v),节点u都在节点v之前。这一排序在解决工程依赖、课程安排等问题时非常有用,Kahn算法和DFS算法都是实现拓扑排序的有效方法。 ...

    Scratch编程入门与算法进阶.pptx

    这些问题包括约瑟夫环问题、最长回文子串、0/1背包问题、拓扑排序等。通过这些实例,读者可以深入理解算法的本质和实现方法,提高解决问题的能力。该部分还介绍了一些常见的算法优化技巧,如空间换时间、分治策略等...

    ACM入门训练指南

    这些包括排序(快速排序、归并排序、堆排序)、搜索(二分查找、深度优先搜索、广度优先搜索)、图论(最短路径、最小生成树、拓扑排序)等。理解这些算法的工作原理,并能快速应用到实际问题中,是解决问题的关键。...

    算法竞赛入门经典授课教案第6章数据结构基础.doc

    (7)掌握拓扑排序算法和欧拉回路算法。 教学难点: (1)掌握完全二叉树的数组实现和链式表示法。 (2)掌握二叉树的先序、后序和中序遍历和层次遍历。 (3)掌握图的 DFS 和 BFS 遍历。 (4)掌握拓扑排序...

    ACM国际大学生程序设计竞赛 知识与入门-高清-完整目录-2012年12月

    2. 图论算法:最短路径(Dijkstra、Floyd-Warshall)、最小生成树(Prim、Kruskal)、拓扑排序等。 3. 贪心算法:在每一步选择局部最优解,以期望得到全局最优解,如活动安排、区间调度问题。 4. 回溯法:用于解决...

    数据结构从入门到大师

    除了基本数据结构,还有高级数据结构如堆(用于优先队列)、哈希表(提供快速的查找和插入操作)和图算法(如最短路径算法Dijkstra和拓扑排序)。这些数据结构和算法在实际编程中有着广泛的应用,如数据库索引、搜索...

    acm基础训练题(动态规划等。。。。。。)

    14. **一笔画问题**:图形理论问题,需要找到一个闭合路径,使得图形仅被一笔画出,可以使用拓扑排序或欧拉路径。 15. **城市遍历问题**:可能是指旅行商问题(TSP),寻找访问所有城市的最短路径,属于NP完全问题...

    练习题程序.rar

    5. **第五题**:这可能是一个涉及算法的题目,比如图论问题(如最短路径、拓扑排序)或动态规划。也可能与数据结构的高级主题相关,如树(二叉树、红黑树等)或哈希表的操作。 6. **第六题**:第六题可能与对象导向...

    算法竞赛入门经典(小白)标程

    3. **图论**:包括最小生成树(Prim或Kruskal)、最短路径(Dijkstra或Floyd-Warshall)、拓扑排序和网络流等,这些都是解决复杂关系网络问题的工具。 4. **动态规划**:动态规划是一种用于求解具有重叠子问题和最...

    算法入门必做题

    3. **图论**:包括最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树(Prim算法、Kruskal算法),以及拓扑排序等,这些都是解决实际网络问题的关键。 4. **动态规划**:背包问题、最长公共子序列、...

    数据结构入门教程

    图算法包括最短路径查找(Dijkstra算法、Bellman-Ford算法)、拓扑排序等。 9. **排序算法**:如冒泡排序、选择排序、插入排序、快速排序、归并排序等,它们用于将一组元素按特定顺序排列。 10. **查找算法**:如...

    算法入门 Wrox.Beginning.Algorithms

    7. **图算法**:包括最短路径问题(如Dijkstra算法和Floyd算法)、拓扑排序、最小生成树(Prim和Kruskal算法)等。 8. **数据结构**:算法离不开数据结构的支持,如链表、栈、队列、树、图、哈希表等,书中会介绍...

    算法竞赛入门经典习题原题

    6. **图论**:包括图的遍历、最小生成树(Prim或Kruskal)、最短路径(Dijkstra或Floyd-Warshall)、拓扑排序、网络流等。这些在解决复杂关系问题时非常有用。 7. **数据结构**:如链表、栈、队列、哈希表、树...

    ACMer 必知必会(入门必看)

    算法是解决问题的核心,常见的有排序(如冒泡、快速、归并排序)、查找(如二分查找)、图论(如最短路径、拓扑排序)等。数据结构如栈、队列、链表、树(二叉树、平衡树)和哈希表等,是实现高效算法的基石。理解...

    ACM培训讲义全集【看完就入门了】

    2. **图论**:图的概念广泛应用于ACM竞赛中,包括最小生成树(Prim算法或Kruskal算法)、最短路径(Dijkstra算法或Floyd-Warshall算法)以及拓扑排序等。 3. **动态规划(Dynamic Programming, DP)**:DP是一种...

    ACM入门资料(大学内部)

    2. **图论**:如最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树(Prim算法、Kruskal算法)、拓扑排序等,这些都是处理复杂关系网络的关键。 3. **动态规划**:动态规划能有效地解决具有重叠子问题...

    ACM入门资料

    DFS可以用来检查图中是否存在环,以及用于网络的拓扑排序。 #### 3. DFS的实际运用 DFS在解决许多图论问题中都十分有用,例如迷宫求解、电路检测、以及各种路径寻找问题。通过实践DFS算法,参赛者能加深对图和树的...

    Python解答蓝桥杯省赛真题之从入门到真题

    2. **算法基础**:蓝桥杯竞赛中常见的算法包括排序(如冒泡排序、快速排序、归并排序)、查找(如线性查找、二分查找)、图论(如最短路径问题、拓扑排序)和动态规划等。掌握这些基础算法有助于高效解题。 3. **...

    算法入门教材

    深度优先搜索是图遍历的基本算法之一,通常用于拓扑排序和检测环等问题。 5. 图中的路径 路径算法部分关注如何在图中找到两点间最短路径。涉及到了距离的计算、广度优先搜索(BFS)、Dijkstra算法以及负权边和有向...

    刘汝佳书籍代码

    在"aoapc-bac2nd-master"这个压缩包中,我们可以期待找到各种不同类型的算法实现,如排序算法(快速排序、归并排序、冒泡排序等)、查找算法(二分查找、哈希查找等)、图算法(最短路径、拓扑排序等)、树算法...

Global site tag (gtag.js) - Google Analytics