(正在尝试使用标准目录)
【拓扑】师徒关系
一道C++编程问题。
题目大意
在学习圈中,总会有人互相帮助。如果一个人帮助了另一个人,我们称帮助者是被帮助者的师傅,被帮助者是帮助者的徒弟。一个人可能会有多个师傅,也可能会有多个徒弟。师徒关系可能会在几个人之间继承,如 a a a是 b b b的师傅, b b b是 c c c的师傅,则 a a a也是 c c c的师傅。
如果一个人同时是另一个人的师傅和徒弟,那么这两人在学习圈的师徒关系就是不合法的。例如 a a a是 b b b的师傅, b b b是 c c c的师傅, c c c是 a a a的师傅,则 a 、 b 、 c a、b、c a、b、c之间的关系不合法。
现在题目会输入几组学习圈的师徒系统,请你判断每一组数据里是否存在不合法的关系。
输入描述
输入多组数据,对于每一组数据,第一行是两个整数 n n n和 m m m ( 2 < = n , m < = 100 ) (2<=n,m<=100) (2<=n,m<=100),表示 n n n个人之间有 m m m组师徒。接下来 m m m行,每一行是两个整数 x x x和 y y y ( 0 < = x , y < n ) (0<=x,y<n) (0<=x,y<n),表示 x x x是 y y y的师傅。所有数据输入完毕后,输入 ( 0 , 0 ) (0,0) (0,0)表示结束。
输出描述
对于每一组数据,输出YES
或 NO
,表示数据中师徒关系是否全部合法。
数据样例
输入
3 2
0 1
1 2
2 2
0 1
1 0
0 0
输出
YES
NO
解题思路
很简单的一道题,我们可以把师徒关系抽象成有向图图象,把人看成图中的点,师徒关系是图中的边。这样,就可以用拓扑排序的理论来解决这道题。合法的师徒关系一定是一条路有尽头,永远不会出现回路。可以用宽搜来做这道题。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,a[1005][1005],p[100005];
//n和m存数据量,x和y用于输入,a[][]存师徒关系,p[]存每人的师傅有几人
bool bfs(){//此函数用于遍历每一组数据
int sum=0,t;
queue<int> q;
for(int i=0;i<n;i++) if(p[i]==0) q.push(i);
//将没有师傅的人入队,这些人可以作为师傅进入下一轮筛选
while(!q.empty()){//开始深搜
t=q.front(),sum++;//sum记录出队次数
for(int i=0;i<n;i++) if(a[t][i]){//将出队的人的所有徒弟的师傅数量-1
p[i]--;
if(p[i]==0) q.push(i);//将没有师傅的人入队
}
}
return sum==n;//如果队列中出现了回路,肯定会有人无法出队,所以出队次数不等于总人数
}
int main(){
while(cin>>n>>m){
if(!n&&!m) break;//判断结束
memset(a,0,sizeof(a));
memset(p,0,sizeof(p));//每组数据前清空数组
for(int i=1;i<=m;i++){
cin>>x>>y;//依次输入关系
p[y]+=(a[x][y]==0),a[x][y]=1;//记录两人关系和徒弟的师傅数量
}
if(f()) cout<<"YES\n";
else cout<<"NO\n";//判断输出,记得换行
}
return 0;
}
感谢观看