淺談 拓撲排序
阿新 • • 發佈:2018-09-28
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;} inlineint 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
淺談 拓撲排序