標籤:拓撲排序
轉載請註明出處:http://blog.csdn.net/u012860063?viewmode=contents
----------------------------------------------------------------------------------------------------------------------------------------------------------
歡迎光臨天資小屋:http://user.qzone.qq.com/593830943/main
----------------------------------------------------------------------------------------------------------------------------------------------------------
一、輸出任意一種滿足優先條件的即可:
代碼如下:
#include <cstdio>#include <cstring>#define MAXN 517int G[MAXN][MAXN];int c[MAXN],topo[MAXN];int t;int n, m;bool dfs(int u){c[u] = -1;for(int v = 1; v <= n; v++){if(G[u][v]){if(c[v] < 0)return false;else if(!c[v] && !dfs(v))return false;}}c[u] = 1;topo[--t] = u;return true;}bool toposort(){t = n;memset(c,0,sizeof(c));for(int u = 1; u <= n; u++){if(!c[u]){if(!dfs(u))return false;}}return true;}int main(){int a, b;int i;while(~scanf("%d%d",&n,&m)){for(i = 0; i < m; i++){scanf("%d%d",&a,&b);G[a][b] = 1;}if(toposort()){bool ok = true;for(i = 0; i < n; i++){if(ok){printf("%d",topo[i]);ok = false;}elseprintf(" %d",topo[i]);}}printf("\n");}return 0;}
二、輸出滿足條件且要求輸出時編號小的在前:
此時需要用到優先隊列;
拓撲排序首先統計每個結點的入度。將度為0的結點編號放入
隊列(此題放入優先隊列中)中。然後進行迴圈:
- 取出隊頭結點,視作邊的起點。
- 然後“刪除與該點相連的邊”,代碼就是將這個圖中的該邊另一個結點(即終點)的入度減一;
- 如果減一以後,終點的入度變為了0,那麼將終點的編號入隊列。
- 判斷隊列是否為空白,若不空,則回到1
優先隊列C++ STL中有優先隊列的類——priority_queue<T>。預設優先隊列是值越大,優先順序越高。所以比如priority_queue<int> q。這裡面的元素是降序排列的。如果我們要實現升序需要重載。
priority_queue<int,vector<int>,greater<int> > q;
代碼如下:(HDU1285)
#include<iostream>#include<queue>#include<cstdio>#include<cstring>using namespace std;bool map[517][517];int in[517];priority_queue<int,vector<int>,greater<int> > q;void topo(int n){ for(int i=1;i<=n;i++) { if(in[i]==0) q.push(i); } int c=1; while(!q.empty()) { int v=q.top(); q.pop(); if(c!=n) { cout<<v<<" "; c++; } else cout<<v<<endl; for(int i=1;i<=n;i++) { if(!map[v][i]) continue; in[i]--; if(!in[i]) q.push(i); } }}int main(){ int n,m,i,j; while(cin>>n>>m) { int k=0; memset(map,0,sizeof map); memset(in,0,sizeof in); while(m--) { cin>>i>>j; if(map[i][j]) continue; map[i][j]=1; in[j]++; } topo(n); }}
三、直接每次先輸出入度為零的點:(HDU1285)
代碼如下:
#include <cstdio>#include <cstring>#define MAXN 517int G[MAXN][MAXN];//路徑int in_degree[MAXN];//入度int ans[MAXN];int n, m, x, y;int i, j;void toposort(){for(i = 1; i <= n; i++){for(j = 1; j <= n; j++){if(G[i][j]){in_degree[j]++;}}}for(i = 1; i <= n; i++)//從最小的開始尋找,{//這樣保證了有多個答案時序號小的先輸出int k = 1;while(in_degree[k] != 0)//尋找入度為零的點k++;ans[i] = k;in_degree[k] = -1;//更新為-1,後邊檢測不受影響,相當於刪除節點for(int j = 1; j <= n; j++){if(G[k][j])in_degree[j]--;//相關聯的入度減1}}}void init(){memset(in_degree,0,sizeof(in_degree));memset(ans,0,sizeof(ans));memset(G,0,sizeof(G));}int main(){while(~scanf("%d%d",&n,&m)){init();for(i = 0; i < m; i++){scanf("%d%d",&x,&y);G[x][y] = 1;}toposort();for(i = 1; i < n; i++)printf("%d ",ans[i]);printf("%d\n",ans[n]);}return 0;}
以上講解的都是二維的用的是鄰接矩陣存圖,只適用於稠密圖,資料多大就不能存了;
下面是用鄰接表存圖的拓撲排序, 適用於大資料,稀疏圖!
一、數組式鄰接表:
代碼如下:
#include <iostream>using namespace std;int ind[517]; // indegree入度個數int adj[250017]; //adjacency list鄰接表位置值int adj_next[250017];//鄰接表下一指標int tail[517]; //鄰接表尾int main(){ int n,m,i,j,a,b; while(scanf("%d%d",&n,&m)!=EOF) { for(i = 0; i <= n; i++) { tail[i] = -1; adj[i] = -1; adj_next[i] = -1; ind[i] = 0; } for(i = 0; i < m; ++i) { scanf("%d%d",&a,&b); int x = tail[a],flag = 0; while(x != -1) //判斷是否重邊 { if(adj[x] == b){ flag = 1; break; } x = adj_next[x]; } if(!flag)//關聯a的鄰接表 { adj[i] = b; adj_next[i] = tail[a]; tail[a] = i; ind[b] ++; } } for(i = 1;i <= n; i++)//找n次 { for(j = 1;j <= n;j++)//遍曆 { if(ind[j] == 0)//當入度為0時,說明靠前{ind[j] = -1;//在下次尋找入度為0時跳過 if(i == 1) printf("%d",j); else printf(" %d",j); for(int k = tail[j]; k != -1; k = adj_next[k])//鄰接位置入度減一 { ind[adj[k]]--; } break; } } } printf("\n"); } return 0;}
二、結構體(鏈表)式鄰接表:
代碼如下:
#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<cstdio>#include<queue>#include<bitset>using namespace std;#define maxn 505struct node{ int num; node *next;};node map[maxn];int d[maxn], n;void Insert(int a, int b);void Free();void Topsort();int main(){ int m; while(cin >> n >> m) { int i, a, b; memset(d, 0, sizeof(d)); for(i=0; i<m; i++) { cin >> a >> b; Insert(a, b); d[b]++; } Topsort(); Free(); } return 0;}void Insert(int a, int b){ node *newnode; newnode = (node *)malloc(sizeof(node)); newnode->num = b; newnode->next = map[a].next; map[a].next = newnode;}void Free(){ node *cur, *old; for(int i=1; i<=n; i++) { cur = map[i].next; while(cur) { old = cur; cur = cur->next; free(old); } map[i].next = NULL; }}void Topsort(){ priority_queue<int, vector<int>, greater<int> > que; int nx, i; int q[maxn]={0}, k=0; node *cur; for(i=1; i<=n; i++) { if(d[i] == 0) que.push(i); } while(que.size()) { nx = que.top(), que.pop(); q[k++] = nx; cur = map[nx].next; while(cur) { nx = cur->num; d[nx] -= 1; if(d[nx] == 0) que.push(nx); cur = cur->next; } } cout << q[0]; for(i=1; i<k; i++) cout <<" "<< q[i]; cout <<endl;}
拓撲排序(待更新模板)