[HDU] 1285 确定比赛名次- 稍微变下的拓扑排序
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1285
方法:以后比赛名次以前到后的有向边建立好有向图,然后开始拓扑排序。排序的方式为将入度为0的点压入优先队列,优先弹出其中序号最小的出队列,输出,然后扫描其所有指向的端点,将端点的入度减1,如果减少为0后,也同样压入优先队列,如果优先队列有多个入度减少为0的点,则下一次就又再优先弹出序号最小的,以此循环。最终比赛名次排出。
感想:该题重点在于考察在拓扑排序的时候,如何才能在出现了两个入度为0的端点时,要优先输出的是序号比较小的。
代码:
View Code
#include<iostream> #include<queue> //#include<map> //#include<string> //#include <algorithm> using namespace std; //int const MAX =0x3f3f3f3f; //int const MIN=-1; bool matrix[501][501]; int indegree[501]; struct Arc { int node; Arc* nextArc; }; struct Node { Arc* firstArc; }; Node* nodes[501]; void createArc(int x,int y) { Arc* arc = (Arc*)malloc(sizeof(Arc)); arc->node = y; if(nodes[x]->firstArc == NULL) arc->nextArc = NULL; else arc->nextArc = nodes[x]->firstArc; nodes[x]->firstArc = arc; } struct cmp { bool operator ()(int x, int y) { return x>y; } }; int main() { int n,m; while(scanf("%d %d", &n, &m) == 2) { memset(matrix,false,sizeof(matrix)); memset(indegree,-1,sizeof(indegree)); int i = 0; for(i=1;i<=n;i++) { nodes[i] =(Node*) malloc(sizeof(Node)); nodes[i]->firstArc=NULL; indegree[i] = 0; } int a,b; i= 0; while(i<m) { scanf("%d %d",&a,&b); if(a!=b && matrix[a][b]==false) { matrix[a][b] = true; indegree[b]++; createArc(a,b); } i++; } priority_queue<int,vector<int>,cmp> q; for(i=1;i<=n;i++) { if(indegree[i]==0) q.push(i); } int k =0; while(!q.empty()) { int temp = q.top(); q.pop(); if(k==0) cout<<temp; else cout<<" "<<temp; Arc * t_arc = nodes[temp]->firstArc; k++; while(t_arc!=NULL) { indegree[t_arc->node]--; if(indegree[t_arc->node]==0) q.push(t_arc->node); t_arc= t_arc->nextArc; } } cout<<endl; } return 0; }