标签:
思路:
选择一个入度为0的顶点并输出,从网中删除此顶点及所有出边。
循环结束后,若输出的定点数小于网中的顶点数,则输出有回路信息,否则输出的顶点就是一种拓扑序列。
具体实现方法:邻接表,时间复杂度较小,邻接矩阵,时间复杂度高
确定比赛名次
Problem Description
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
Input
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
Sample Input
4 3
1 2
2 3
4 3
Sample Output
1 2 4 3
邻接矩阵实现:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int map[505][505]; int indegree[505]; int output[505]; int main() { int n,m,a,b; while(scanf("%d%d",&n,&m)==2) { memset(map,0,sizeof(map)); memset(indegree,0,sizeof(indegree)); while(m--) { scanf("%d%d",&a,&b); if(map[a][b]==0) { map[a][b]=1; indegree[b]++; } } int i=0; while(i<n) { for(int j=1; j<=n; j++) { if(indegree[j]==0) { indegree[j]--; output[i++]=j; for(int k=1; k<=n; k++) if(map[j][k]) { indegree[k]--; map[j][k]=0; } break; } } } for(int i=0; i<n-1; i++) printf("%d ",output[i]); printf("%d\n",output[n-1]); } return 0; }
邻接表实现:
#include<iostream> #include<queue> #include<cstring> using namespace std; //有向图的邻接表 typedef struct v { int vex;//终点的序号 v *next;//与这条有向边具有相同起点的其它有向边 } V; //边结点 typedef struct h { int indegree;//入度 v *next;//指向((从该节点出发的有向边的)边结点所组成的单链表) } H; //头结点 H team[10010]; V *p; int main() { int i,n,m,a,b,count; priority_queue<int,vector<int>,greater<int> > q; while(cin>>n>>m) { memset(team,0,sizeof(team)); while(m--) { //加入一条a->b的有向边 cin>>a>>b; team[b].indegree++; p=new V; p->vex=b; p->next=team[a].next; team[a].next=p; } //输出拓扑排序 for(i=1; i<=n; i++) if(team[i].indegree==0) q.push(i); count=0; while(!q.empty()) { a=q.top(); q.pop(); if(count) cout<<‘ ‘; cout<<a; count++; for(p=team[a].next; p!=0; p=p->next) { b=p->vex; if(--team[b].indegree==0) q.push(b); } } cout<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/a-clown/p/5917946.html