拓扑顺序 Java代码(判断拓扑序列的合法性)【PAT甲级1146】

58 篇文章 3 订阅
32 篇文章 1 订阅

输入样例:

6 8
1 2
1 3
5 2
5 4
2 3
2 6
3 4
6 4
5
1 5 2 3 6 4
5 1 2 6 3 4
5 1 2 3 6 4
5 2 1 6 3 4
1 2 3 4 5 6

输出样例:

3 4

算法思路:

拓扑序列是在有向无环图中的任意一条边的两点,在序列中始终是从前指向后的。所以在判断拓扑序列时,只需要遍历所有的边,检查是否在序列中满足从前指向后。

由于拓扑序列的最开始的顶点入度一定为0,也可以检查序列的入度情况,并将以该顶点的出度为入度的顶点入度减去,判断序列的入度是否始终未为0。

Java代码:(判断所有边的方向)

import java.io.*;
import java.util.ArrayList;

public class Main {
	static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	public static int ini() throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	
	static class Node{
		int a, b;
		public Node(int a, int b) {
			this.a = a;
			this.b = b;
		}
	}
	
	public static void main(String[] args) throws IOException {
		int n = ini(), m = ini();
		
		Node []node = new Node[m];
		for(int i = 0; i < m; i++) 
			node[i] = new Node(ini(), ini());
		
		int q = ini();
		int []p = new int[n + 1];
		int []arr = new int[n];
		ArrayList<Integer> ans = new ArrayList<>();
		for(int i = 0; i < q; i++) {
			
			for(int j = 0; j < n; j++) {
				arr[j] = ini();
				p[arr[j]] = j; // 哈希序列中的点的位置
			}
			
			int j = 0;
			for(j = 0; j < m; j++) 
				if(p[node[j].a] > p[node[j].b])
					break;
			
			if(j != m) ans.add(i);
		}
		
		System.out.print(ans.get(0));
		for(int i = 1; i < ans.size(); i++) System.out.print(" " + ans.get(i));
	}
}

Java代码:(判断入度)

import java.io.*;
import java.util.*;

public class Main1639 {
	static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	public static int ini() throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	static int n, m, N = 1005, M = 10005, idx;
	static int[]e = new int[M];
	static int[]ne = new int[M];
	static int[]h = new int[N];
	
	public static void main(String[] args) throws IOException {
		n = ini();
		m = ini();
		int[]d = new int[n + 1];
		Arrays.fill(h, -1);
		
		while(m-- > 0) {
			int a = ini(), b = ini();
			add(a, b);
			d[b]++;
		}
		
		int q = ini();
		int []arr = new int[n + 1];
		int []bd = new int[n + 1];
		ArrayList<Integer> ans = new ArrayList<>();
		for(int p = 0; p < q; p++) {
			bd = Arrays.copyOf(d, n + 1);  // 先将图的入度数组备份
			for(int i = 1; i <= n; i++) arr[i] = ini();
			
			for(int i = 1; i <= n; i++) {
				int t = arr[i];
				if(bd[t] == 0) {  // 入度为0顶点
					for(int j = h[t]; j != -1; j = ne[j]) {
						int k = e[j];  // 该顶点的邻接边
						bd[k]--;  // 入度减一
					}
				}else {
					ans.add(p);  // 遍历到不满足入度为0时为不合法情况
					break;
				}
			}
		}
		System.out.print(ans.get(0));
		for(int i = 1; i < ans.size(); i++) System.out.print(" " + ans.get(i));
	}
	
	public static void add(int a, int b) {
		e[idx] = b;
		ne[idx] = h[a];
		h[a] = idx++;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值