HDU 1285 確定比賽名次(拓撲排序模板)
阿新 • • 發佈:2017-11-28
href 正在 ios dfs als 結束 top 查找 names
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1285
題目大意:有N個比賽隊(1<=N<=500),編號依次為1,2,3,。。。。,N進行比賽,比賽結束後,裁判委員會要將所有參賽隊伍從前往後依次排名,但現在裁判委員會不能直接獲得每個隊的比賽成績,只知道每場比賽的結果,即P1贏P2,用P1,P2表示,排名時P1在P2之前。現在請你編程序確定排名。
解題思路:拓撲排序裸題,但是有要求並列的點序號小的排在前面。開始寫了一個dfs版倒序的怎麽寫都錯,後來發現根本做不了(可能是我太菜了)。。。。於是改寫了一個通過每次查找入讀為0的點,然後刪除有關邊的版本,一下就AC了。
先是對了的方法,先叫它減入度法吧,這種做法可以判斷有向圖是否成單鏈,也就是沒有分支,若一次找到入度為0的點有兩個則存在分支。
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int N=5e2+5; 7 8 int n,m; 9 int degree[N]; 10 bool G[N][N]; 11 queue<int>q; 12 13 void toposort(){ 14 for(int i=1;i<=n;i++){ 15 //尋找出度為0的點 16 int j=1; 17 while(degree[j]!=0) j++; 18 degree[j]--; 19 q.push(j); 20 //將關聯的點的入度減1,即刪除與該節點關聯的邊 21 for(int k=1;k<=n;k++){ 22 if(G[j][k]) 23 degree[k]--;24 } 25 } 26 } 27 28 int main(){ 29 while(~scanf("%d%d",&n,&m)){ 30 memset(G,false,sizeof(G)); 31 memset(degree,0,sizeof(degree)); 32 for(int i=1;i<=m;i++){ 33 int a,b; 34 scanf("%d%d",&a,&b); 35 if(!G[a][b]){ 36 G[a][b]=true; 37 degree[b]++; 38 } 39 } 40 toposort(); 41 while(!q.empty()){ 42 if(q.size()==1) 43 printf("%d\n",q.front()); 44 else 45 printf("%d ",q.front()); 46 q.pop(); 47 } 48 } 49 return 0; 50 }
然後是dfs版的,雖然不能寫這題,但還是當個模板放著吧,dfs法可以在O(n^2)時間內判斷是否有環,而floyd需要O(n^3)。
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<stack> 5 using namespace std; 6 const int N=5e2+5; 7 8 int n,m; 9 int G[N][N],vis[N];//vis[i]=0,-1,1分別表示未訪問、正在訪問、已訪問並且已遞歸訪問完所有子孫 10 stack<int>res; 11 12 13 bool dfs(int u){ 14 vis[u]=-1; 15 for(int i=1;i<=n;i++){ 16 if(G[u][i]){ 17 if(vis[i]<0) return false; 18 else if(!vis[i]&&!dfs(i)) 19 return false; 20 } 21 } 22 vis[u]=1; 23 res.push(u); 24 return true; 25 } 26 27 bool toposort(){ 28 memset(vis,0,sizeof(vis)); 29 for(int i=1;i<=n;i++){ 30 if(!vis[i]){ 31 if(!dfs(i)) return false; 32 } 33 } 34 return true; 35 } 36 37 int main(){ 38 while(~scanf("%d%d",&n,&m)){ 39 memset(G,0,sizeof(G)); 40 for(int i=1;i<=m;i++){ 41 int a,b; 42 scanf("%d%d",&a,&b); 43 G[a][b]=1; 44 } 45 toposort(); 46 while(!res.empty()){ 47 if(res.size()==1) 48 printf("%d\n",res.top()); 49 else 50 printf("%d ",res.top()); 51 res.pop(); 52 } 53 } 54 return 0; 55 }
HDU 1285 確定比賽名次(拓撲排序模板)