zoukankan      html  css  js  c++  java
  • 拓扑排序 POJ 1094 Sorting It All Out

    题意:给定N个字和M行他们之间的关系,要求输出他们的拓扑排序。此题采用边输入边检测的方式,如果发现环,就结束并输出当前行号;如果读取到当前行时,可以确定拓扑序列就输出,不管后面的输入(可能包含环路);如果到最后还是不能确定拓扑序列,就输出指定的字符串。

    拓扑排序:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若 ∈E(G),则u在线性序列中出现在v之前。

    分析:首先,拓扑排序的算法还是挺直观的。简单的拓扑排序算法:先找到任意一个没有入边的顶点,然后是显示该顶点,并将它和它的边一起从图中删除。然后,对图的其余部分应用同样的方法处理。如果找不到没有入边的顶点,说明存在回路。这里的实现过程由于要边输入边检测,所以要注意先一次性读取完输入。还要注意图不是强连通的,以及消去一个顶点后的图不是强连通图的这种情况。做的时候感觉要考虑很多情况,但做完了反而想不起那么多来。呵呵,看代码吧!

    import java.util.Scanner;
    
    public class Main {
    	static int n,m;
    	static int[][] a; //邻接矩阵
    	static int [] degree; //每个节点的入度
    	static boolean[] vis; //记录是否被访问
    	/**
    	 * 拓扑排序,返回排序的序列,返回1说明存在环路。
    	 * @return
    	 */
    	public static String topo(){
    		String s="";
    		for(int i=0;i<n && isIsolatedNode(i);i++){
    			int temp=findInDegreeZero();
    			if(temp!=-1){
    				//消去顶点后的图还是强连通就满足要求
    				if(countZeroDegree()==1)
    					s+=((char)(temp+65));
    				vis[temp]=true;
    				for(int j=0;j<n;j++)
    					if(a[temp][j]==1)
    						degree[j]--;
    			}else{
    				s="1";
    				break;
    			}
    		}
    		return s;
    	}
    	/**
    	 * 读取入度
    	 */
    	public static void readInDegree(){
    		for(int i=0;i<n;i++)
    			for(int j=0;j<n;j++)
    				if(a[i][j]!=0 )
    					degree[j]++;
    	}
    	/**
    	 * 由于采用邻接矩阵,所以要判断节点是否在要排序的N个节点中。利于查找入度为0的节点。
    	 * @param num
    	 * @return
    	 */
    	public static boolean isIsolatedNode(int num){
    		int sum=0;
    		for(int i=0;i<n;i++)
    			sum+=(a[num][i]+a[i][num]);
    		if(sum==0)
    			return false;
    		else
    			return true;
    	} 
    	/**
    	 * 计算入度为零的节点个数,超过一个则说明该图不是强连通图。
    	 * 由于要优先判断是否存在环路,所以不能如果不是强连通图也要等判断是否存在环路。
    	 * @return
    	 */
    	public static int countZeroDegree(){
    		int sum=0;
    		for(int i=0;i<n;i++)
    			if(degree[i]==0 && isIsolatedNode(i) && vis[i]==false){
    				sum++;
    			}
    		return sum;
    	}
    	/**
    	 * 找到入度为0的节点,不存在就返回-1(存在环路)
    	 * @return
    	 */
    	public static int findInDegreeZero(){
    		for(int i=0;i<n ;i++)
    			if(degree[i]==0 && vis[i]==false && isIsolatedNode(i)){
    				return i;
    			}
    		return -1;   
    	}
    	
    	public static void main(String[] args) {
    		Scanner sc=new Scanner(System.in);
    		while(true){
    			n=sc.nextInt();
    			m=sc.nextInt();
    			if(n+m==0)
    				break;
    			a=new int[n][n];
    			String result="";
    			String[] str=new String[m+1];
    		    for(int i=1; i<=m; i++)
    		        str[i]=sc.next();
    		    int i;
    		    for(i=1; i<=m; i++){
    		    	vis=new boolean[n];
    		    	degree=new int[n];
    		        a[str[i].charAt(0)-65][str[i].charAt(2)-65]=1;
    		        readInDegree();
    		        int beginZeroDegree=countZeroDegree();
    		        result=topo();
    		        //如果结果字符串长度和N相同,并且图是强连通的就输出序列
    		        if(result.length()==n && beginZeroDegree==1){
    		        	System.out.println("Sorted sequence determined after "+i+" relations: "+result+".");
    		        	break;
    		        //如果存在环路则输出
    		        }else if(result.equals("1")){
    		        	System.out.println("Inconsistency found after "+i+" relations.");
    		        	break;
    		        }
    		    }
    		    //不存在环路,到最后还是不能确定序列
    		    if((i-1)==m && result.length()!=n)
    		    	System.out.println("Sorted sequence cannot be determined.");
    		}
    	}
    }
    



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    java中public、private、protected区别
    Java构造函数
    吸血鬼数字算法
    JsonConvert.DeserializeObject<T>对象属性为空
    vs2015项目引用其他项目无法引用
    iis express 无法访问此网站
    c#Dictionary保存不同类型
    HttpContext.GetOwinContext().Authentication 报错 解决办法
    CSS基础1
    CSS基础3
  • 原文地址:https://www.cnblogs.com/AndyDai/p/4734110.html
Copyright © 2011-2022 走看看