Toposort 拓扑排序的应用 判断图中是否存在回路

拓扑排序是面试考试中的高频考点,尤其需要重视;

此外 ,一个重要结论:一个图存在拓扑序  等价于 该图为有向无环图

相关理论参考另一篇博客—— 图的应用 | 拓扑排序

【问题描述】

给出一个有向图,判断图中是否存在回路。

【输入形式】

首先输入整数m,表示m种测试情况。接下来是每种测试情况的输入数据。

每种测试情况包含几行:

第1行:输入图的顶点个数N(1 ≤ N≤ 2,500)和C(图的边数,1 ≤ C ≤ 6,200);

第2到C+1行中,第i+1行输入两个整数,分别表示第i条边的起点和终点的编号。


【输出形式】

对于每种情况输出一行,如果图中存在回路,输出“YES”,否则,输出“NO”。

【样例输入】

1 7 8 1 2 1 3 2 4 2 6 3 4 4 5 5 2 5 7

【样例输出】

YES

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef struct ListNode {
	int Node;
	ListNode* next;
}*List;

int main() {
	int m; cin >> m;
	while (m--) {
		int N, E; cin >> N >> E;
		vector<List> LGraph(N+1);
		vector<int>num(N+1);
		for (int i = 1; i < N+1; i++) {
			LGraph[i] = nullptr; num[i]=0;
		}
		for (int i = 0; i < E; i++) {
			int v1, v2;
			cin >> v1 >> v2;
			ListNode* node = new ListNode;
			node->Node = v2;num[v2]++;
			node->next = LGraph[v1]; LGraph[v1] = node;
			
		}
		queue<int>zero;
		for (int i = 1; i < N+1; i++)
			if (num[i] == 0)zero.push(i);
		int anc = 0;
		while (!zero.empty()) {
			int top = zero.front(); 
			zero.pop();anc++;
			for (ListNode* tem = LGraph[top]; tem; tem = tem->next)
				if (--num[tem->Node] == 0)zero.push(tem->Node);
		}
		if (N == anc)cout << "NO" << endl;
		else cout << "YES" << endl;
	
	}
}

拓扑排序的经典应用!!!要记住!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常感谢您的提问!关于您的问题,我可以给出以下实现代码: ```c #include <stdio.h> #define MAX_N 100 //最大节点数 int indegree[MAX_N]; //每个节点的入度 int G[MAX_N][MAX_N]; //有向图的邻接矩阵 int topo[MAX_N]; //存放拓扑序列 int topoSort(int n) //n为节点个数,返回是否有环 { int i, j, k = 0; int q[MAX_N], front = 0, rear = -1; //队列 for(i = 0; i < n; i++) if(indegree[i] == 0) q[++rear] = i; //将入度为0的节点加入队列 while(front <= rear) //队列非空时循环 { int u = q[front++]; //取出队首节点 topo[k++] = u; //将该节点加入拓扑序列 for(j = 0; j < n; j++) //遍历该节点的所有出边 if(G[u][j]) //如果存在一条出边 if(--indegree[j] == 0) q[++rear] = j; //将该出边对应节点的入度减一 //如果该节点的入度变为0,将其加入队列 } return k == n; //如果拓扑序列中包含所有节点,说明没有环 } int main() { int n, m, i, u, v; //n为节点数,m为有向边数 scanf("%d%d", &n, &m); for(i = 0; i < m; i++) { scanf("%d%d", &u, &v); G[u][v] = 1; //有向图中u到v存在一条边 indegree[v]++; //节点v的入度加1 } if(topoSort(n)) //如果不存在环 { printf("拓扑序列为:\n"); for(i = 0; i < n; i++) printf("%d ", topo[i]); printf("\n"); } else { printf("有向图中存在环!\n"); } return 0; } ``` 此算法利用了拓扑排序的思想,如果有向图中存在环,那么必然至少有一个节点的入度不为零,无法入队,因此无法输出拓扑序列。如果有向图中不存在环,那么每个节点的入度都可以为零,将它们全部入队,按照入队时的顺序输出,即可得到一个拓扑序列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值