拓撲排序node
int k=0; void toposort() { queue<int>q; for(int i=1;i<=n;i++) if(!indegree[i]) q.push(i); while(!q.empty()){ int u=q.front(); q.pop(); cout<<u<<' ';k++;//輸出拓撲序列,計數+1 for (u的每一個鄰接點v){ //vector或鏈式前向星建圖,遍歷方式不同 indegree[v]--;//刪除邊(u, v),即讓v的入度-1; if (!indegree(v) ) q.push(v); } } } if (k!=n) 存在環; else 不存在環,爲DAG圖;
②基於DFS的拓撲排序算法( 複雜度O(V+E) )ios
1)DFS求給定DAG圖的拓撲序列【前提:已知圖是DAG】c++
topo數組存求得的拓撲序列 int k=0; void DFS(int x) { vis[x]=1; for(遍歷x的鄰接點j){ if(!vis[j]) DFS(j); } topo[k++]=x;//用棧存 } void toposort() { for(int i=1;i<=n;i++){ //遍歷每一個頂點 if(!vis[i]) DFS(i); } for(int j=k-1;j>=0;j--) cout<<topo[i]<<' ';//逆序輸出數組,所得序列即爲拓撲序列 }
2)DFS判斷有向圖是否有環(是否存在合法的拓撲序列):算法
對一個節點x進行dfs,判斷是否能從x回到本身這個節點,便是否存在x到x的迴路。數組
這裏需用一個color數組標記節點的狀態:-1表明未訪問,0表明正在被訪問,1表明已被訪問過spa
#include<bits/stdc++.h> using namespace std; int n,e;//n個頂點(1<=n<=100),e條邊 int color[105];//color數組表示每一個結點的狀態 vector<int>G[105];//vector鄰接表建圖 bool flag;//爲真則存在環 void DFS(int x) { if(flag)//若是有環就返回,否者繼續搜索 return; color[x]=0;//x正在被訪問,狀態爲0 for(int i=0;i<G[x].size();i++){ if(color[G[x][i]]==-1)//與x相連的結點狀態爲-1,則該節點未被訪問,繼續搜索 dfs(G[x][i]); else if(color[G[x][i]]==0){//與x相連的結點狀態也爲0,表明有環,返回 flag=true; return; } } color[x]=1;//標記x狀態爲已被訪問過了 } int main() { int u,v; while(~scanf("%d%d",&n,&e)) { flag=false; for(int i=1;i<=n;i++)//二維vector初始化 for(int j=0;j<G[i].size();j++) G[i].pop_back(); memset(color,-1,sizeof(color));//初始化爲未訪問 for(int i=1;i<=e;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); } DFS(1); if(!flag) printf("有向圖無環,存在合法的拓撲序列\n"); else printf("有向圖有環,不存在合法的拓撲序列\n"); } return 0; }
UVA10305 給任務排序 Ordering Tasks.net
題意code
John有n個任務要作,每一個任務在作以前要先作特定的一些任務。blog
輸入第一行包含兩個整數n和m,其中1<=n<=100。 n表示任務數,而m表示有m條任務之間的關係。 接下來有m行,每行包含兩個整數i和j,表示任務i要在j以前作。排序
當讀入兩個0(i=0,j=0)時,輸入結束。
輸出包含q行,每行輸出一條可行的安排方案。
輸入:
5 4 1 2 2 3 1 3 1 5 0 0
輸出:
1 4 2 5 3
題解
裸拓撲排序
Code
Kahn算法+vector鄰接表
#include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; int n,m,indegree[105]; void toposort(vector<vector<int> >G) { int space=0; queue<int>q; for(int i=1;i<=n;i++) if(!indegree[i]) q.push(i); while(!q.empty()){ int x=q.front();q.pop(); space?printf(" "):printf(""),space=1; printf("%d",x); for(int j=0;j<G[x].size();j++){ indegree[G[x][j]]--; if(!indegree[G[x][j]]) q.push(G[x][j]); } } } int main() { int u,v; while(~scanf("%d%d",&n,&m)&&n) { vector<vector<int> >G(n+5);//開n+5行的vector二維數組 indegree[105]={}; while(m--){ scanf("%d%d",&u,&v); G[u].push_back(v); indegree[v]++; } toposort(G); puts(""); } return 0; }
基於DFS的拓撲排序+鏈式前向星建圖
#include<cstdio> #include<cstring> #include<iostream> #include<queue> using namespace std; struct node{ int to,next; }G[105]; int head[105],cnt; void add(int u,int v) { G[cnt].to=v; G[cnt].next=head[u]; head[u]=cnt++; } int n,e,indegree[105],ans[105],k,vis[105]; void DFS(int rec) { vis[rec]=1; for(int j=head[rec];~j;j=G[j].next){ if(!vis[G[j].to]) DFS(G[j].to); } ans[k++]=rec; } void toposort() { for(int i=1;i<=n;i++){ if(!vis[i])DFS(i); } int q=1; for(;k>0;){ q?cout<<"":cout<<" "; q=0; cout<<ans[--k]; } } int main() { int u,v; while(~scanf("%d%d",&n,&e)&&n) { cnt=0; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); for(int i=1;i<=e;i++){ scanf("%d%d",&u,&v); add(u,v); } toposort(); puts(""); } return 0; }