1. 程式人生 > >確定比賽名次(hdu-1285)(拓撲排序佇列實現)

確定比賽名次(hdu-1285)(拓撲排序佇列實現)

分析:
就是找出是否存在拓撲排序。
每次從該集合中取出(沒有特殊的取出規則,隨機取出也行,使用佇列/棧也行,下同)一個頂點,將該頂點放入儲存結果的List中。
緊接著迴圈遍歷由該頂點引出的所有邊,從圖中移除這條邊,同時獲取該邊的另外一個頂點,如果該頂點的入度在減去本條邊之後為0,那麼也將這個頂點放到入度為0的集合中。然後繼續從集合中取出一個頂點…………

當集合為空之後,檢查圖中是否還存在任何邊,如果存在的話,說明圖中至少存在一條環路。不存在的話則返回結果List,此List中的順序就是對圖進行拓撲排序的結果。

本質就是不斷找出入度為0的點,並儲存下來,可以用佇列儲存。

#include<cstdio>
#include<iostream> #include<queue> #include<vector> #include<stack> #include<cstring> using namespace std; const int maxn=1000+5; int indegree[maxn],graph[maxn][maxn];//indegree記錄入度,graph記錄關係 queue<int>ans; //用佇列儲存入度為0的點 int main() { int n,m; while(cin>>n>>m) { if
(n==0&&m==0) break; //初始化陣列 memset(indegree,0,sizeof(indegree)); memset(graph,0,sizeof(graph)); while(!ans.empty()) //清空ans ans.pop(); for(int i=0;i<m;i++) { int a,b; cin>>a>>b; graph[a][b]=1
; } //計算入度 for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(graph[i][j]==1) indegree[j]++; //將入度為0的儲存進ans中 for(int i=0;i<n;i++) if(indegree[i]==0) ans.push(i); int num=0; //記錄次數 while(!ans.empty()) { int v1=ans.front(); //取佇列首元素 num++; ans.pop(); //出隊 //找出以隊首元素為起點的邊,刪除首頂點和與之相連的邊,則末端入度減一 for(int i=0;i<n;i++) { if(graph[v1][i]==1) { indegree[i]--; if(indegree[i]==0) //將入度為0的再放入ans中 ans.push(i); } } } // cout<<res.size()<<endl; if(num==n) cout<<"YES"<<endl; else cout<<"NO"<<endl; } }