hdoj 1285 确定比赛名次 ( 拓扑排序--三种模板 )
2016-08-05 12:22
253 查看
确定比赛名次
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 22388 Accepted Submission(s): 9063
[align=left]Problem Description[/align]
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
[align=left]Input[/align]
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
[align=left]Output[/align]
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
[align=left]Sample Input[/align]
4 3
1 2
2 3
4 3
[align=left]Sample Output[/align]
1 2 4 3
三种方式模板
<1>二维数组(邻接矩阵)
#include<cstdio> #include<cstring> int map[510][510]; int indegree[510]; int queue[510]; void topo(int n) //拓扑排序 { int m,t=0; for(int i=0;i<n;i++) //遍历每个顶点,对n个顶点进行排序 { for(int j=1;j<=n;j++) //第一步:选取一个没有前驱(入度为0)的结点,(或并输出 ) { if(indegree[j]==0) { m=j; break; } } queue[t++]=m;indegree[m]--;//保存 ,第二步:①删去该点 for(int k=1;k<=n;k++) // ②并删去从该出发的有向边 { if(map[m][k]) indegree[k]--; } } printf("%d",queue[0]); for(int i=1;i<n;i++) printf(" %d",queue[i]); printf("\n"); } int main() { int n,m; int a,b; while(~scanf("%d%d",&n,&m)) { memset(map,0,sizeof(map)); memset(indegree,0,sizeof(indegree)); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); if(map[a][b]==0) //构图,防止有重边 { map[a][b]=1; indegree[b]++; } } topo(n); } return 0; }<2>邻接表
#include<cstdio> #include<cstring> int indegree[510]; int queue[510]; //邻接表:(1)结构体 (2)初始化 (3)加边函数 struct Edge { int to,next; }edge[500+10]; int head[500+10],top; void init() { top=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v) { Edge E={v,head[u]}; edge[top]=E; head[u]=top++; } void topo(int n) { int m,t=0; for(int i=0;i<n;i++) //遍历n个顶点,对n个顶点的排序 { for(int j=1;j<=n;j++) //第一步:选取一个没有前驱(入度为0)的结点,(或并输出 ) { if(indegree[j]==0) { m=j; break; } } queue[t++]=m; indegree[m]--; //保存 ,第二步:①删去该点 for(int k=head[m];k!=-1;k=edge[k].next) // ②并删去从该出发的有向边 { Edge E=edge[k]; if(indegree[E.to]) indegree[E.to]--; } } printf("%d",queue[0]); //输出拓扑序 for(int i=1;i<n;i++) printf(" %d",queue[i]); printf("\n"); } int main() { int n,m,a,b; while(~scanf("%d%d",&n,&m)) { memset(indegree,0,sizeof(indegree)); init(); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); addedge(a,b); indegree[b]++; } topo(n); } return 0; }
<3>优先队列
#include<cstdio> #include<cstring> #include<queue> using namespace std; int map[510][510]; int indegree[510]; void topo(int n) { priority_queue<int, vector<int>, greater<int> > Q; while(!Q.empty()) Q.pop(); for(int i=1;i<=n;i++) //第一步:加入所有没有前驱的顶点 { if(indegree[i]==0) { Q.push(i); } } int flag=1; while(!Q.empty()) { int a=Q.top(); //取队头,输出,(flag控制格式) Q.pop(); indegree[a]--; if(flag) printf("%d",a); else printf(" %d",a); flag=0; for(int i=1;i<=n;i++) //第二步:删去由该点指向的有向边 { if(map[a][i]) {//注意:再次加点,是在删去入度的点中加入入度为0的点 indegree[i]--; if(indegree[i]==0)// Q.push(i); } } } printf("\n"); } int main() { int n,m,a,b; while(~scanf("%d%d",&n,&m)) { memset(map,0,sizeof(map)); memset(indegree,0,sizeof(indegree)); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); if(map[a][b]==0) //构图 { map[a][b]=1; indegree[b]++; } } topo(n); } return 0; }
相关文章推荐
- HDOJ题目1285确定比赛名次(拓扑排序,模板)
- HDU-1285-确定比赛名次-拓扑排序(模板)
- HDOJ 1285 确定比赛名次(拓扑排序)
- HDU-1285-确定比赛名次【拓扑排序模板】
- HDU 1285 确定比赛名次 拓扑排序模板题
- HDOJ--1285 确定比赛名次(拓扑排序)
- HDOJ 1285 确定比赛名次(拓扑排序)
- HDOJ1285 确定比赛名次(拓扑排序)
- hdoj 1285 确定比赛名次【拓扑排序】
- HDU 1285 确定比赛名次(拓扑排序的三种实现方法)
- HDOJ 1285 确定比赛名次(拓扑排序)
- hdoj.1285 确定比赛名次【拓扑排序】 2015/03/30
- hdoj 1285 确定比赛名次 【拓朴排序】三种方法实现。
- 确定比赛名次 1285(拓扑排序 模板)
- hdoj1285-确定比赛名次(拓扑排序)
- HDOJ1285 确定比赛名次(拓扑排序)
- HDOJ 确定比赛名次 1285【拓扑排序】
- hdoj 1285 确定比赛名次 【拓扑排序】
- hdu 1285 确定比赛名次 简单的拓扑排序模板题~~需要注意重边
- HDOJ1285 确定比赛名次(拓扑排序)