题目描述
给定一个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
输入样例:
1 2
2 3
1 3
输出样例:
1 2 3
Go 代码
方法1,多创建一个跟队列q一样的切片,用来保存结果
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const N = 100010
var (
n, m ,idx int
e,ne,h[N]int
d [N]int //记录每个点的 "度",有"出度"和"入度"
q,qq []int //bfs的队列
)
func add(a,b int) {
e[idx] = b
ne[idx] = h[a]
h[a] = idx
idx ++
}
func readline(r *bufio.Reader)[]int {
s,_:=r.ReadString('\n')
ss :=strings.Fields(s)
res :=make([]int,len(ss))
for i,v :=range ss{
res[i],_ = strconv.Atoi(v)
}
return res
}
func topsort()bool {
for i:=1;i<=n;i++{
if d[i]==0{ // 将入度为0的点插入到队列中
q =append(q,i)
qq =append(qq,i)
}
}
for len(q)>0{
t :=q[0]
q = q[1:]
for i:=h[t];i!=-1;i=ne[i]{ // 枚举t的所有出边 t->j
j:=e[i] // 删除t->j这条出边
d[j]--
if d[j]==0{
// 放入队列
q =append(q,j)
qq =append(qq,j)
}
}
}
return len(qq)==n
}
func main() {
fmt.Scan(&n, &m)
r :=bufio.NewReader(os.Stdin)
for i:=0;i<N;i++{
h[i]=-1
}
for i:=0;i<m;i++{
in :=readline(r)
a,b :=in[0],in[1]
add(a,b)
d[b]++ // 点b增加"入度"
}
if topsort(){
for i:=0;i<n;i++{
fmt.Print(qq[i]," ")
}
}else{
fmt.Println(-1)
}
}
算法2 只创建一个模拟队列q的切片
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const N = 100010
var (
n, m ,idx int
e,ne,h[N]int
d [N]int //记录每个点的 "度",有"出度"和"入度"
q[N]int //bfs的队列
)
func add(a,b int) {
e[idx] = b
ne[idx] = h[a]
h[a] = idx
idx ++
}
func readline(r *bufio.Reader)[]int {
s,_:=r.ReadString('\n')
ss :=strings.Fields(s)
res :=make([]int,len(ss))
for i,v :=range ss{
res[i],_ = strconv.Atoi(v)
}
return res
}
func topsort()bool {
hh,tt :=0,-1 // 头尾
for i:=1;i<=n;i++{
if d[i]==0{ // 将入度为0的点插入到队列中
tt++
q[tt] = i
}
}
for hh<=tt{
t :=q[hh]
hh++
for i:=h[t];i!=-1;i=ne[i]{ // 枚举t的所有出边 t->j
j:=e[i] // 删除t->j这条出边
d[j]--
if d[j]==0{
// 放入队列
tt++
q[tt] = j
}
}
}
return tt==n-1
}
func main() {
// fmt.Scan(&n, &m)
r :=bufio.NewReader(os.Stdin)
//fmt.Scan(&n, &m)
w:= readline(r)
n,m = w[0],w[1]
for i:=0;i<N;i++{
h[i]=-1
}
// r :=bufio.NewReader(os.Stdin)
for i:=0;i<m;i++{
in :=readline(r)
a,b :=in[0],in[1]
add(a,b)
d[b]++ // 点b增加"入度"
}
if topsort(){
for i:=0;i<n;i++{
fmt.Print(q[i]," ")
}
}else{
fmt.Println(-1)
}
}