POJ1094(拓扑排序)

POJ1094(拓扑排序)


Sorting It All Out

Description

An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

Input

Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character “<” and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

Output

For each problem instance, output consists of one line. This line should be one of the following three:

Sorted sequence determined after xxx relations: yyy…y.
Sorted sequence cannot be determined.
Inconsistency found after xxx relations.

where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy…y is the sorted, ascending sequence.

Sample Input

4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0

Sample Output

Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
题意

有 1 ~ N 个大写字母,且从 A 开始依次 N 个。再给你 M 个小于的关系,比如 A < B ,让你判断三种可能:

1、在第 i 个关系罗列之后,是否可以满足使得这 N 个字母能递增关系。

2、在第 i 个罗列之后,是否会出现矛盾,例如 A > B,而在第 i 个状态出现后,B > A ,故矛盾。

3、如果 M 个条件罗列完后都没有出现矛盾,且还无法判断 N 个字母的排列顺序,则输出 Sorted sequence cannot be determined.

思路

对于 A < B,我们建一个 A --> B 的有向图。

每输入一条关系,进行一次拓扑排序:

  • 如果某一次拓扑之后发现存在环路,结束并输出"Inconsistency found after 2 relations."(其中2为第几步)。
  • 如果在拓扑排序过程中,某一次判断存在入度为0的点不止一个,跳过此次拓扑排序,输入下一条关系。
  • 如果所有关系输入完成,拓扑序列不唯一确定。输出"Sorted sequence cannot be determined."。
  • 如果在第i关系之后,拓扑排序已经唯一确定,输出"Sorted sequence determined after i relations: ABCD."(ABCD为最终的拓扑排序)

注意:当序列有多种拓扑顺序且还有环存在时,输出的结果应该为有环存在的情况。所以每次拓扑排序都需要完整的做完,而不是当有多个入度为0的顶点的时候就返回。

代码
package _topologicalSort.problem1094;

import java.util.Scanner;

public class SortingItAllOut {
  public static int max = Integer.MAX_VALUE;

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    SortingItAllOut sortingItAllOut = new SortingItAllOut();
    while (true) {
      int n = sc.nextInt();//字母个数
      int m = sc.nextInt();//关系数量
      if (m == 0 && n == 0) {
        break;
      }
      int[][] graph = new int[n][n];
      char[] nodes = new char[n];
      for (int i = 0; i < n; i++) {//初始化图
        nodes[i] = (char) (65 + i);//大写字母A到ASCII为65
        for (int j = 0; j < n; j++) {
          if (i == j) {
            graph[i][j] = 0;
          } else {
            graph[i][j] = max;
          }
        }
      }
      int step = 0;
      String result = "";
      boolean flag = false;
      for (int i = 0; i < m; i++) {
        String str = sc.next();
        if (flag) {//已经唯一确定或已经存在环路
          continue;
        }
        step++;
        char from;
        char to;
        if (str.charAt(1) == 60) {//小于号的ASCII为60,输入一条关系,判断这条关系的起点和终点
          from = str.charAt(0);
          to = str.charAt(2);
        } else {
          from = str.charAt(2);
          to = str.charAt(0);
        }
        graph[from - 65][to - 65] = 1;//将这条关系更新到图中,大写字母A到ASCII为65
        result = sortingItAllOut.topologicalSort(graph, nodes);
        if (result.equals("ring")) {//存在环路
          System.out.println("Inconsistency found after " + step + " relations.");
          flag = true;
        } else if (!result.equals("notUnique")) {//唯一确定排序
          System.out.println("Sorted sequence determined after " + step + " relations: " + result + ".");
          flag = true;
        }
      }
      if (result.equals("notUnique")) {
        System.out.println("Sorted sequence cannot be determined.");
      }
    }
  }

  public String topologicalSort(int[][] graph1, char[] nodes) {
    int[][] graph = new int[graph1.length][graph1.length];
    for (int i = 0; i < graph.length; i++) {
      for (int j = 0; j < graph.length; j++) {
        graph[j][i] = graph1[j][i];
      }
    }
    String result = "";
    int[] nums = new int[graph.length];//记录顶点的入度
    boolean flag = true;
    boolean notUnique = false;//是否唯一
    boolean ring = false;//是否存在环路
    while (flag) {
      flag = false;
      for (int i = 0; i < graph.length; i++) {//统计每个顶点的入度
        if (nums[i] == -1) {//此顶点已经输出过
          continue;
        }
        int num = 0;
        for (int j = 0; j < graph.length; j++) {
          if (graph[j][i] != 0 && graph[j][i] != max) {
            num++;
          }
        }
        nums[i] = num;
      }
      int count = 0;//入度为0的点到个数
      int index = -1;//入度为0的点的下标
      for (int i = 0; i < nums.length; i++) {
        if (nums[i] == 0) {//如果某个顶点的入度为0。
          count++;
          index = i;
        }
      }
      if (count > 0) {//存在入度为0的点
        result = result + nodes[index];
        nums[index] = -1;
        for (int j = 0; j < graph.length; j++) {//删除所有以该点为起点的边
          graph[index][j] = max;
        }
        flag = true;
      }
      if (count > 1) {//入度为0的点不止1个
        notUnique = true;//拓扑排序不唯一
      }
    }
    for (int i = 0; i < nums.length; i++) {
      if (nums[i] != -1) {//有点没有输出,存在回路
        ring = true;
      }
    }
    if (ring) {//存在环路
      result = "ring";
    } else if (notUnique) {
      result = "notUnique";
    }
    return result;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值