图论--拓扑排序 有向图的拓扑序列 java

拓扑序列:序列中任意两个数,前面的数都存在指向后面的数的有向边,反之则不成立,用于有向无环图,类似于:确定工程施工顺序

有向无环图又称为拓扑图


https://www.acwing.com/problem/content/850/
给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

输入格式
第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)。

输出格式
共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

否则输出 −1。

数据范围
1≤n,m≤105
输入样例:
3 3
1 2
2 3
1 3
输出样例:
1 2 3

import java.util.*;

public class Main
{
	static int n,m,idx,M=100005,N=M;
	static int e[]=new int [M],ne[]=new int [M],h[]=new int [N],d[]=new int [N];
	static int q[]=new int [N],hh,tt,t;
	
	static void add(int a,int b)
	{
		e[idx]=b;ne[idx]=h[a];h[a]=idx++;
	}
	static boolean topsort()
	{
		hh=0;tt=-1;
		for(int i=1;i<=n;++i)
		{
			if(d[i]==0)q[++tt]=i;
		}
		while(hh<=tt)
		{
			t=q[hh++];
			for(int i=h[t];i!=-1;i=ne[i])
			{
				int j=e[i];
				d[j]--;
				if(d[j]==0)q[++tt]=j;
			}
		}
		if(tt==n-1)return true;
		return false;
	}
	
	
	public static void main(String args[])
	{
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		Arrays.setAll(h, x->-1);
		for(int i=0;i<m;++i)
		{
			int a,b;
			a=sc.nextInt();
			b=sc.nextInt();
			add(a,b);
			d[b]++;
		}
		if(topsort())
		{
			for(int i=0;i<n;++i)System.out.print(q[i]+" ");
		}
		else System.out.println(-1);
	}
}
posted @ 2022-11-17 23:03  林动  阅读(65)  评论(0编辑  收藏  举报