概念:一個有向無環圖的拓撲序列是將圖中的頂點排成一個線性序列,使得對於圖中任意一對頂點u,v。若存在邊<u,v>,則線性序列中u出現在v之前。
算法實現:
(1)若圖中的點入度均大於0則不存在拓撲序列,否則進行第二步
(2)取一個入度為0的點u並將其放置序列末尾
(3)刪除點u以及從u伸出的邊,即將與u相連的點的入度減1
(4)若圖中還存在頂點,再從(1)開始
模板:
#include<cstdio> #include<vector> #include<cstring> #include<queue> #include<iostream> using namespace std; const int maxn=1e3; vector<int>grid[maxn]; int indu[maxn]; void find(int n){ queue<int>Q; for(int i=1;i<=n;i++)if(indu[i]==0)Q.push(i),cout<<i<<","; while(!Q.empty()){ int now=Q.front();Q.pop(); for(int i=0;i<grid[now].size();i++){ int next=grid[now][i]; if(--indu[next]==0)Q.push(next),cout<<next<<","; } } cout<<endl; } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++)grid[i].clear(); memset(indu,0,sizeof(indu)); for(int i=0;i<m;i++){ int p1,p2; scanf("%d%d",&p1,&p2); grid[p1].push_back(p2);//p1到p2有一條邊 indu[p2]++; } find(n); } return 0; }
題目:
基本應用之有向圖判環:在while循環中加入計數,當循環結束時如果循環次數等於頂點個數,則證明n個頂點入度都已經為0 ,存在拓撲序列,則圖中不存在環,反之有環,題目:HUD-3342
學會反向建圖及按題意確定輸出次序:HUD-1285
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #define MM(a) memset(a,0,sizeof(a)); using namespace std; const int maxn=510; vector<int>grid[maxn]; int indu[maxn]; void find(int N){ priority_queue<int,vector<int>,greater<int> >Q; for(int i=1;i<=N;i++)if(indu[i]==0)Q.push(i); vector<int>ans; while(!Q.empty()){ int now=Q.top();Q.pop(); //printf("-%d-\n",now); ans.push_back(now); for(int i=0;i<grid[now].size();i++){ int next=grid[now][i]; if(--indu[next]==0)Q.push(next); } } for(int i=0;i<ans.size();i++){ printf("%d",ans[i]); if(i==ans.size()-1)printf("\n"); else printf(" "); } } int main(){ int N,M; while(scanf("%d%d",&N,&M)==2 &&N){ for(int i=1;i<=N;i++)grid[i].clear(); MM(indu); for(int i=0;i<M;i++){ int p1,p2; scanf("%d%d",&p1,&p2); grid[p1].push_back(p2);//p2輸給p1 indu[p2]++; } find(N); } return 0; }
福利題:poj-3687 Labeling Balls(別問我福利是啥,做了就知道了,嘿嘿)