第一道应用拓补排序的题目,应用拓补排序判断有无环。谨记:目前(这句话是做完所有拓补排序的题后写的)接触过的拓补排序的应用只有两个:
1.利用拓扑排序确定拓扑序列;2.在确定拓扑序列的过程中判断该有向图是否是无环图
-
题目描述:
-
ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exchange their ideas. When someone has questions, many warm-hearted cows like Lost will come to help. Then the one being helped will call Lost "master", and Lost will have a nice "prentice". By and by, there are many pairs of "master and prentice". But then problem occurs: there are too many masters and too many prentices, how can we know whether it is legal or not?We all know a master can have many prentices and a prentice may have a lot of masters too, it's legal. Nevertheless,some cows are not so honest, they hold illegal relationship. Take HH and 3xian for instant, HH is 3xian's master and, at the same time, 3xian is HH's master,which is quite illegal! To avoid this,please help us to judge whether their relationship is legal or not. Please note that the "master and prentice" relation is transitive. It means that if A is B's master ans B is C's master, then A is C's master.
-
输入:
-
The input consists of several test cases. For each case, the first line contains two integers, N (members to be tested) and M (relationships to be tested)(2 <= N, M <= 100). Then M lines follow, each contains a pair of (x, y) which means x is y's master and y is x's prentice. The input is terminated by N = 0.TO MAKE IT SIMPLE, we give every one a number (0, 1, 2,..., N-1). We use their numbers instead of their names.
-
输出:
-
For each test case, print in one line the judgement of the messy relationship.If it is legal, output "YES", otherwise "NO".
-
样例输入:
-
3 2 0 1 1 2 2 2 0 1 1 0 0 0
-
样例输出:
-
YES NO
//适用条件:题目给的这张图只能有一个(弱)连通分量(但不要求强连通)
#include <iostream>
#include <vector>
#include <queue>
#define MAXSIZE 300
using namespace std;
struct Edge{
int thisNode;
int nextNode;
Edge(){
}
Edge(int thisNode,int nextNode){
this->thisNode=thisNode;
this->nextNode=nextNode;
}
};
struct Vex{
};
struct Graph{
int graphSize;
vector<Edge> edge[MAXSIZE];
// vector<Vex> vex;
void initGraph(int graphSize){
this->graphSize=graphSize;
for (int i=0;i<graphSize;i++)
edge[i].clear();
// vex.clear();
}
void addEdge(int thisNode,int nextNode){
edge[thisNode].push_back(Edge(thisNode,nextNode));
}
};
int main(){
int n,m;
Graph graph;
int inDegree[MAXSIZE];
int cnt;
queue<int> q,seq;
int thisNode,nextNode;
while (cin>>n>>m,n){
//initiate
graph.initGraph(n);
for (int i=0;i<graph.graphSize;i++)
inDegree[i]=0;
while (!q.empty())
q.pop();
while (!seq.empty())
seq.pop();
cnt=0;
//input & cal inDegree
for (int i=0;i<m;i++){
cin>>thisNode>>nextNode;
graph.addEdge(thisNode,nextNode);
inDegree[nextNode]++;
}
//initiate q
for (int i=0;i<graph.graphSize;i++){
if (inDegree[i]==0)
q.push(i);
}
//Topological sorting
/*
使用队列q作为线索,利用了"新出现的入度为0的点必定是由边的删除造成的"这一特性,对顶点进行遍历,较之自己的算法逻辑更优
使用了cnt计数器与顶点总数n比较来判定是否顶点皆已删除,较之自己的算法逻辑更优
*/
while(!q.empty()){
int nowP=q.front();
seq.push(nowP);//record the seq
q.pop();//del the vex
cnt++;
for (int i=0;i<graph.edge[nowP].size();i++){//traverse the edges & reduce inDegree
int nextNode=graph.edge[nowP][i].nextNode;
inDegree[nextNode]--;
if (inDegree[nextNode]==0)
q.push(nextNode);
}
graph.edge[nowP].clear();//del the edges
}
//output
cout<<(cnt==n?"YES":"NO")<<endl;
}
return true;
}
/**************************************************************
Problem: 1448
User: bit3125
Language: C++
Result: Accepted
Time:10 ms
Memory:1524 kb
****************************************************************/