话不多说,先上图!!!
聪明的你,可以发现每次都是先输出入度为0的点(类似于入口),然后删除与此点相关的边,然后继续同样的操作。经过如此反复操作,如果图中的点都输出了,就说明此图是无环有向图,否则就是有环图。
比如说这里的环CED,BD,环中任意一点入度都不为0,根本找不到入口。所以没法遍历完所有的点
对于题目给定了众多两点之间的优先级关系,然后让你判断所有点之间的是否构成优先级。
- 现在来介绍一个模板题
有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
简单来说,存图时需要记录每个点的入度数(用数组),以及记录一个出度邻接表(vector)。把入度为0的点都放入到队列中。队列每出队一个,就将此点出度相连的点入度-1,减的过程中,又出现了入度为0点的时候,再把入度为0的点加入到队列。
最后遍历一遍入度数的数组,若数组中全入度为0,则图遍历完毕,不存在环,否则肯定存在环。
#include <bits/stdc++.h> using namespace std; const int NN = 550; int in[550];//in[i]:点i的入度次数 int N,M; int main(){ while(cin>>N>>M){ vector<int> out[550];//out[i]:点i出度相连的点 priority_queue<int, vector<int>, greater<int> > q;//优先队列,从小到大排列 memset(in,0,sizeof(in)); int win,lo; //赢 输 for(int i = 1;i<=M;i++){ scanf("%d%d",&win,&lo); out[win].push_back(lo); //以赢->输的关系存储的 in[lo]++;//谁输了,谁的入度+1 } for(int i = 1;i<=N;i++){ //将入度为0的点加入到优先队列 if(in[i] == 0) q.push(i); } int tag = 0;//题目要求,末尾不加空格 while(!q.empty()){ int x = q.top(); q.pop();//删除入度为0的点 if(tag) cout<<" "; tag = 1; cout<<x; for(int i = 0;i<out[x].size();i++){ //将x出度相连的点入度-1,相当于删除边 in[out[x][i]]--; if(in[out[x][i]] == 0){//某点度为0,就加入到优先队列中 q.push(out[x][i]); } } } cout<<endl; } return 0; }