图论之拓扑排序各种写法
图的存储主要有邻接矩阵与邻接表两种写法,其中邻接表多采用vector<Edge> edge[N]方式模拟单链表简化存储。
struct Edge { int nextNode;//下一个节点编号 int cost;//该边权重 }; vector<Edge> edge[N];//为每个节点都模拟一个单链表 //清空,添加,遍历,删除 edge[i].clear(); edge[i].push_back(); for(int i=0;i<edge[2].size();i++){}; edge[2].erase(edge[2].begin()+i,edge[2].begin()+i+1);//删除edge[2][i]
BFS拓扑:
vector<int> edge[501]; queue<int> Q;//入度为0的节点队列 int inDegree[501]; init();//初始化,读入邻接表 while(Q.empty()==false)Q.pop();//清空上一组测试遗留数据 for(int i=0;i<n;i++) { if(inDegree[i]==0)Q.push(i); } int cnt=0; while(Q.empty()==false) { int nowP=Q.front(); Q.pop(); cnt++; for(int i=0;i<edge[nowP].size();i++) { inDegree[edge[nowP][i]]--; if(inDegree[edge[nowP][i]]==0) Q.push(edge[nowP][i]); } } if(cnt==n)puts("DAG"); else puts("circle");
DFS+stack拓扑:
vector<int> Edge[N];//假设无权值 int vis[N],top=0,stack[N]; void topo_sort(int x) { vis[x] = 1; for(int i=0;i<Edge[x].size();i++) { if(vis[Edge[x][i]] == 0) topo_sort(Edge[x][i]); } stack[top++] = Edge[x][i]; }
此时的stack也可用链表头插法,两者等价,作用为转化逆拓扑序列。
附:邻接表的写法也有采用数组的与vector模拟单链表类似,代码如下:
int head[N];//child正向 vector<int> p[maxn];//parent反向 struct Edge { int to; int next; }edge[MAXN]; int cnt=0; void addEdge(int u,int v) { edge[cnt].to = v; edge[cnt].next=head[u]; head[u]=cnt++; } void init() { memset(head,-1,sizeof(head)); memset(inDegree,0,sizeof(inDegree)); for(int i = 0; i <= n; i++) p[i].clear(); } //添加 addedge(u,v); //child正向 p[v].push_back(u); //parent反向 inDegree[v]++; //indegree //遍历 for(int i = head[u]; i != -1; i = edge[i].next){};