拓扑排序(topological sort)
一、定义:
对一个有向无环图(Directed Acyclic Graph简称DAG) G进行拓扑排序
是将G中所有顶点排成一个线性序列
使得图中任意一对顶点u和v
若边(u,v)∈E(G)
则u在线性序列中出现在v之前
注意:
有时候,这里的排序不是唯一的
二、算法 O(V+E)
有两种:入度表、dfs
(一)、入度表 O(V+E):
找出图中0入度的点
依次在图中删除这些点
于是再找删掉点之后的0入度的点
然后再删除...再找点
入度为0的点 用 队列
图 用 邻接表
#include<cstdio> #include<algorithm> #include<queue> using namespace std; const int maxn = 10005; int n,m,cnt;//cnt存储ans数组的下标 bool a[maxn][maxn];//邻接矩阵 int edge[maxn],ans[maxn];//edge[i]第i个点的入度,ans答案队列 queue<int> q; void topo_sort() { for(int i = 1;i <= n;i++) if(!edge[i]) q.push(i);//将所有入度为0的点加入队列中 while(!q.empty()) { const int u = q.front(); ans[++cnt] = u; q.pop(); for(int i = 1;i <= n;i++) if(a[u][i]) { edge[i]--; if(!edge[i]) q.push(i); } } } int main() { scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++) { int x,y; scanf("%d%d",&x,&y); a[x][y] = 1; edge[y]++; } topo_sort(); if(cnt < n) { printf("有环\n"); return 0; } for(int i = 1;i <= n;i++) printf("%d ",ans[i]); return 0; }
(二)、dfs O(n2)
(又要咕咕咕了...也不知道要咕多久qwq)
(洛谷居然出了一片日报,嘎!)
(dfs只能判断有没有还环??!(hushuobadao
用一个int类型的visit数组 标记节点
其中-1表示回到自己(即 产生了环) 这届return
否则,跑一边这个图,跑完了就没有环
//拓扑排序dfs(只判断是否有环 #include<cstdio> #include<algorithm> using namespace std; const int maxn = 10005; int n,m; bool a[maxn][maxn];//邻接矩阵建图 bool flag;//判断是否有环,有环就true int vis[maxn];//标记节点,注意是int类型,因为要用到-1,1,0 void dfs(int k) { vis[k] = -1;//特殊标记 for(int i = 1;i <= n;i++) { if(vis[i] == 0 && a[k][i] == true) { dfs(i); vis[i] = 1; } if(vis[i] == 1 && a[k][i] == true) { printf("有环\n"); flag = true; return; } } } int main() { scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++) { int x,y; scanf("%d%d",&x,&y); a[x][y] = true; } dfs(1); if(!flag) printf("无环\n"); return 0; }
(我..算不算没gu很久wa.)