1. 程式人生 > >淺談 拓撲排序

淺談 拓撲排序

sdi 排序 基礎 ios printf 關系 putchar mes pan

我是什麽時候想到要學拓撲排序的呢?

在一次模考的時候,有這樣一道題,叫做食物鏈,我是寫了記憶化搜索的,然而全場都寫了拓撲板子

後來發現我居然不會這麽基礎的算法,有點慌

下面進入正題


拓撲排序是針對一些特殊問題的,類似於在完成某一件是之前,有必要條件,要先完成另外的一些任務

只有有向無環圖才有拓撲排序,這就關系到了定義

拓撲排序是先排入度為零的點,然後把所有的與之有關的邊都刪掉,這時就又會有一些如度為零的點出現

然以後循環上述操作

這就是拓撲排序的基本概念

還是舉個例子吧

如圖:
技術分享圖片

我們發現1的如度為零

所以先把1刪掉,把與1有關的邊刪掉

技術分享圖片

然後就發現2的入度變成了零

然後會重復上述操作

得到了這個圖的與拓撲排序:1 2 3 4 5

下面給出代碼:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
inline int min(int a,int b){return a<b?a:b;}
inline 
int max(int a,int b){return a>b?a:b;} inline int rd() { int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==-) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-0; return x*f; } inline void write(int x) { if(x<0) putchar(-),x=-x; if(x>9) write(x/10
); putchar(x%10+0); } int n,m; int head[100006],nxt[100006],to[100006]; int in[100006]; int total=0; void add(int x,int y){//鄰接表存邊 total++; in[y]++; to[total]=y; nxt[total]=head[x]; head[x]=total; return ; } int tot=0; int s[100006]; void topo(){ for(int i=1;i<=n;i++) if(!in[i]) s[++tot]=i;//先找出已有的入度為零的點 for(int i=1;i<=tot;i++){ for(int e=head[s[i]];e;e=nxt[e]){//刪除與其相關的邊 in[to[e]]--; if(!in[to[e]]) s[++tot]=to[e];//如果又出現入度為零的點,就入隊 } } return ; } int main() { n=rd(),m=rd(); for(int i=1;i<=m;i++){ int x=rd(),y=rd(); add(x,y);//有向圖單向存邊 } topo(); for(int i=1;i<=n;i++) printf("%d\n",s[i]); return 0; }

可算是填了坑QAQ

淺談 拓撲排序