是否合法题解

该问题是一个图论问题,目标是检测给定的师徒关系图中是否存在环。通过拓扑排序可以判断,如果能成功排序则表示无环(合法),否则存在环(非法)。给出的AC代码使用了邻接表存储图并实现拓扑排序来解决此问题。
摘要由CSDN通过智能技术生成

“是否合法”题目描述


是否合法
时间限制:1秒 内存限制:128M


题目描述
某学习圈中,当有人提出疑问时,许多热情的人会来帮助您。然后,被帮助的那个人将称帮他的人为“师傅”,而提供帮助的人将拥有一个不错的“徒弟”。渐渐地,有许多对“师傅和徒弟”。但是随后出现了问题:师傅太多了,徒弟也太多了,我们怎么知道它是否合法?我们都知道,一个师傅可以有很多徒弟,而一个徒弟可能也可以有很多师傅,这是合法的。但是,有些人并不那么诚实,他们有非法关系。以小可和小达为例,小可是小达的师傅,同时小达是小可的师傅,这是非法的!为避免这种情况,请帮助我们判断他们的关系是否合法。请注意,“师徒”关系是可传递的。这意味着如果AB的师傅,而BC的师傅,则AC的师傅。


输入描述
输入包含多组测试用例。对于每种情况,第一行包含两个整数,N要测试的成员)和M要测试的关系)(2 <= NM <= 100)。


然后是M行,每行包含一对(xy),这意味着x是y的师傅,而y是x的徒弟。
输入以N = 0 && M = 0结束。为简单起见,我们给每个人一个数字(0,1,2,...,N-1)。我们使用他们的数字而不是他们的名字。


输出描述
对于每个测试用例,如果合法,则输出“YES”,否则输出“NO”。


样例

输入

3 2
0 1
1 2
2 2
0 1
1 0
0 0

输出

YES
NO


这道题题目大意为:

给定一个图,要求不能出现,如果出现环,则出现师徒非法关系,所以我们只需要判断图中有没有出现环即可。而拓扑排序正好能够很轻松的判断出一个连通图里是否有环,因为拓扑排序是基于一个没有环的联通图中进行,所以能够成功的排序,则输出YES,反之输出NO

这道题建图可以用邻接表,根据数据量大小来看,邻接矩阵也是没问题的,时间比邻接表稍慢,我先用邻接矩阵写,调了N个小时,一直在错,懒狗的我决定不写啦在这里就先不放出邻接矩阵的代吗了。




Accepted Code

// 邻接表AC代码
# include <cstdio>
# include <cstring>
# include <cmath>
# include <algorithm>
# include <vector>
# include <iostream>
# include <string>
# include <set>
# include <map>
# include <stack>
# include <queue>
# include <deque>
# define pf push_front
# define pb push_back
# define ppf pop_front()
# define ppb pop_back()
# define mp make_pair
# define p_a first
# define p_b second
# define PI acos(-1, 0)
# define LF putchar('\n')
# define SP putchar(' ')
# define repi(a, b) for(int i = (a); i <= (b); i++)
# define repi_(a, b) for(int i = (a); i >= (b); i--)
# define repj(a, b) for(int j = (a); j <= (b); j++)
# define repj_(a, b) for(int j = (a); j >= (b); j--)
# define repk(a, b) for(int k = (a); k <= (b); k++)
# define repk_(a, b) for(int k = (a); k >= (b); k--)
# define WW(x) while((x)--)
# define paix(a, n) sort((a) + 1, (a) + 1 + (n));
# define BUG(z) cout << endl << (z) << endl;
# define lowbit(z) ((z) & (-z))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N1 = 1e6 + 5, N2 = 1e3 + 5, M1 = 1e9 + 7, M2 = 998244353, INF1 = 0x7fffffff, INF2 = 0x3f3f3f3f;
const ll INF = 9223372036854775807;
template <typename T>
void read(T& x) { x = 0; char ch = getchar(); ll f = 1; while (!isdigit(ch)) { if (ch == '-') f *= -1; ch = getchar(); } while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getchar(); } x *= f; }
template <typename T, typename... Args>
void read(T& first, Args&... args) { read(first); read(args...); }
template <typename T>
void write(T arg) { T x = arg; if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x / 10); putchar(x % 10 + '0'); }
template <typename T, typename... Ts>
void write(T arg, Ts... args) { write(arg); if (sizeof...(args) != 0) { putchar(' '); write(args...); } }
void CLOSE() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); }



//  ————————————————————分割线~~~ 
struct node {
	int t, n;
} edge[205];
int head[105];// 邻接表存图
int n, m, ru[105], cnt;
void add(int u, int v) { edge[cnt].t = v; edge[cnt].n = head[u]; head[u] = cnt++; } // 邻接表插入
queue <int> q;
bool bfs() {// 宽搜找拓扑序
	int cnt = -1;
	while(!q.empty()) {
		int t = q.front();
		q.pop(); cnt++;
		for(int i = head[t]; ~i; i = edge[i].n) if (--ru[edge[i].t] == 0) q.push(edge[i].t);
	} return cnt == n;
}
void tain() {
	memset(head, -1, sizeof(head));
	memset(ru, 0, sizeof(ru));
	n--, cnt = 0;
	// 初始化
	int a, b;
	WW(m) {
		scanf("%d%d", &a, &b);
		ru[b]++; add(a, b);
	} repi(0, n) if (ru[i] == 0) q.push(i);
	if (bfs()) puts("YES");
	else puts("NO");
}
signed main() {
	/*
    freopen("", "r", stdin);
    freopen("", "w", stdout);
    */
    while(~scanf("%d%d", &n, &m) && (n || m)) tain();
    /*
    fclose(stdin);
    fclose(stdout);
    */
	return 0;
}

感谢观看
留个赞和评论吧




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值