目录
核心代码
临接表、临接表的添加
数据结构
存储临接表各点数据的数组 e [M]
存储临接表各节点关系的数组 ne [M]
存储临接表起点的数组 h[N]
临接表函数
思路:
把同一起点的有向边存储在一起,边的终点组成链表,后来居上,边的起点指向链表的首结点
int idx = 0 ; //指针 0 memset(h , -1 , sizeof h) //把 h 数组赋值为 -1 void add(int a , int b) //输入:有向边 a->b 的俩结点:a ,b { e[idx] = b; //记录 数组e 第idx个 结点数据内容为 b ne[idx] = h[a]; //这个语句求的是 数组e 第idx个 节点的下一个结点的位置 //如果之前有记录以 a 为起点的边 //那这些边的终点值存储在 数组e 中 //这些节点的 ne值 会组成一个链表,后来居上 //h[a] 记录就是这些边终点节点所构成的链表的首位置 //相当于 b 这个节点下一个节点就是过去的链表 //如果没有记录过以 a 为起点的边 //此时 h[a] 就是初始值 -1 //这个节点下个点是末尾 //所以这个节点的 ne 值赋值为 -1 h[a] = idx++; //记录 a 为起点的有向边,构成的链表的首结点是第 idx 个 }
拓扑排序的思路
数据结构
一位数组队列存储入度为零的节点 queue [N]
存储入度的数组 in_degree [N]
算法思路
遍历各个节点,找到入度为零的节点,存储入一位数组队列(用hh、tt作为头尾指针)
while(hh <= tt) { int temp = queue[hh++]; //遍历这个点各个边的代码 }
遍历队列中节点的各个边,每遍历一条边把终点入度 -1 ,减完入度为 0 则入队
for(int i = h[temp] ; i != -1 ; i = ne[i]) { int j = e[i]; in_degree[j]--; if(!in_degree[j]) { queue[++tt] = j; } }
如果 tt == n - 1 ,说明各个点都遍历了,图无环,否则说明还有点没遍历,图有环
例题:有向图拓扑排序
描述
给定一个n个点m条边的有向图,点的编号是1到n,图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。
若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。
数据范围:1≤n,m≤10^5
输入
第一行包含两个整数n和m
接下来m行,每行包含两个整数x和y,表示存在一条从点x到点y的有向边(x, y)。
输出
共一行,如果存在拓扑序列,则输出拓扑序列。
否则输出-1。
输入样例 1
3 3 1 2 2 3 1 3输出样例 1
1 2 3
题解
*/ #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int N=10; const int M=2*N; int e[M] , ne[M] , h[N] , idx = 0 ; //临接表 int n , m ; //结点的个数、输入行数 int in_degree[N] ; //入度数组 int queue[N] ; //队列 void add(int a , int b) //临接表添加结点的函数 { e[idx] = b; ne[idx] = h[a]; h[a] = idx++; } bool topsort() //拓扑排序的函数 { int hh = 0,tt = -1; for(int i = 1 ; i <= n ; i++) { if(!in_degree[i]) //如果入度为0 { //tt=0,q[++tt]=i; //之前都是直接q[0]=...,此处要初始化入队的数量众多,最好把tt改成-1 queue[++tt] = i; } } while(hh <= tt) { int temp = queue[hh++]; for(int i = h[temp] ; i != -1 ; i = ne[i]) { int j = e[i]; in_degree[j]--; if(!in_degree[j]) { queue[++tt] = j; } } } return tt == n-1; } int main() { cin>>n>>m; memset(h , -1 , sizeof h); while(m--) { int x,y; cin>>x>>y; add(x , y); in_degree[y]++; } if(topsort()) { for(int i = 0 ; i < n ; i++) { printf("%d " , queue[i]); //cout<<endl; } cout<<endl; } else puts("-1"); return 0; }