36. 跳格子游戏

72 阅读2分钟

题目描述

地上共有N个格子,你需要跳完地上所有的格子,但是格子间是有强依赖关系的,跳完前一个格子后,后续的格子才会被开启,格子间的依赖关系由多组steps数组给出,steps[0]表示前一个格子,steps[1]表示steps[0]可以开启的格子:

比如[0,1]表示从跳完第0个格子以后第1个格子就开启了,比如[2,1],[2,3]表示跳完第2个格子后第1个格子和第3个格子就被开启了。

请你计算是否能由给出的steps数组跳完所有的格子,如果可以输出yes,否则输出no。

说明:

1.你可以从一个格子跳到任意一个开启的格子

2.没有前置依赖条件的格子默认就是开启的

3.如果总数是N,则所有的格子编号为[0,1,2,3…N-1]连续的数组

输入描述

输入一个整数N表示总共有多少个格子,接着输入多组二维数组steps表示所有格子之间的依赖关系。

输出描述

如果能按照steps给定的依赖顺序跳完所有的格子输出yes,否则输出no。

用例

# 输入
3  
0 1  
0 2

# 输出
yes

# 说明
总共有三个格子[0,1,2],跳完0个格子后第1个格子就开启了,跳到第0个格子后第2个格子也被开启了,
按照0->1->2或者0->2->1的顺序都可以跳完所有的格子
# 输入
2  
1 0  
0 1

# 输出
no

# 说明
总共有2个格子,第1个格子可以开启第0格子,但是第1个格子又需要第0个格子才能开启,相互依赖,因此无法完成

思路

通过拓扑排序算法来判断一个有向图是否存在环。如果存在环,则无法进行拓扑排序;如果没有环,则可以进行拓扑排序。

#include <iostream>
#include <vector>
#include <map>
#include <deque>
using namespace std;

int main()
{
	int n;
	cin >> n;

	vector<vector<int>> input;
	int s0, s1;
	while (cin >> s0 >> s1)
	{
		input.push_back(vector<int>{s0, s1});
	}

	vector<int> inDegree(n, 0); // 每个顶点的入度
	map<int, vector<int>> next; // 邻接表

	for (int i = 0; i < input.size(); ++i)
	{
		// a --> b
		int a = input[i][0];
		int b = input[i][1];

		inDegree[b]++; // b的入度加1
		next[a].push_back(b); // a指向b
	}

	deque<int>deq;
	for (int i = 0; i < n; ++i)
	{
		if (inDegree[i] == 0)
		{
			deq.push_back(i);
		}
	}

	int count = 0;
	while (!deq.empty()){
		int a = deq.front();
		deq.pop_front();

		count++;

		for (const auto& b : next[a])
		{
			if (--inDegree[b] == 0)
			{
				deq.push_back(b);
			}
		}
	}
	cout << (count == n ? "yes" : "no") << endl;

	return 0;
}