【PTA刷题】甲级 拓扑排序

拓扑排序以前不考,现在考的频率好高。
其实没啥难的,抓住一点:入度为0时,才能被输出(或者被选中,一个意思)。所以要用个int inDegree来维护入度的数量。 当要我们判断一个图能不能是拓扑排序(即没有环),就是看入过队列的节点数是不是就是N。

例题:

判断能不能对某个图做拓扑排序

https://pintia.cn/problem-sets/15/problems/861

大意:给你一个图,让你判断能不能拓扑排序。
输入数据:
输入说明:输入第一行给出子任务数N(≤100),子任务按1~N编号。随后N行,每行给出一个子任务的依赖集合:首先给出依赖集合中的子任务数K,随后给出K个子任务编号,整数之间都用空格分隔。

12
0
0
2 1 2
0
1 4
1 5
2 3 6
1 3
2 7 8
1 7
1 10
1 7

输出:

0

代码:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>

using namespace std;

const int maxnum = 105;
int N;
vector<int> G[maxnum];
int inDegree[maxnum];

bool Judge()
{
    
    
	queue<int> Q;

	for (int i = 1; i <= N; i++)
		if (inDegree[i] == 0)
			Q.push(i);  //把一开始入度为0的入队

	int cnt = 0;
	while (!Q.empty())
	{
    
    
		int u = Q.front();
		Q.pop();
		cnt++; //u加入Top队列

		for (int i = 0; i < G[u].size(); i++)
		{
    
    
			int v = G[u][i];  //u后续节点
			inDegree[v]--; //更新入度
			if (inDegree[v] == 0)
				Q.push(v);
		}
	}

	if (cnt == N)
		return true;
	else return false;

}

int main()
{
    
    
	cin >> N;
	for (int i = 1; i <= N; i++)
	{
    
    
		int num;
		cin >> num;
		inDegree[i] = num; //存储初始入度
		for (int j = 0; j < num; j++)
		{
    
    
			int a;
			cin >> a;
			G[a].push_back(i);
		}
	}

	cout << Judge();


	return 0;
}

判断一个序列是否是拓扑排序的结果序列

1146 Topological Order

输入:
每个输入文件包含一个测试用例。对于每种情况,第一行给出两个正整数N(≤1000),表示图中顶点的数量,M(≤10000)表示有向边的数量。然后有M条线,每条线给出一条边的开始点和结束点。顶点编号从1到n,图后还有一个正整数K(≤100)。然后是K行查询,每一行给出所有顶点的排列。一行中的所有数字都用空格隔开。

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

输出:
在一行中打印所有符合“非拓扑顺序”的查询索引。指标从零开始。所有的数字用空格隔开,行首和行尾都不能有多余的空格。很显然,至少有一个答案。

3 4

思路:对于某个序列来说,一个个把数字读进来,然后判断这个数当前的入度是否是0。如果不是0,则说明违反了拓扑排序。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>

using namespace std;

const int maxnum = 1005;
const int INF = 99999;
int N, M, K;

vector<int> G[maxnum];
int inDegree[maxnum];
vector<int> res;

int main()
{
    
    
	cin >> N >> M;
	
	for (int i = 0; i < M; i++)
	{
    
    
		int a, b;
		cin >> a >> b;
		G[a].push_back(b); //单向图
		inDegree[b]++; //b的入度加一
	}
	cin >> K;
	for (int i = 0; i < K; i++)
	{
    
    
		vector<int> in(inDegree,inDegree+N+1); //每次复制出一个入度副本
		int judge = 1; //初始默认是拓扑排序
		for (int j = 0; j < N; j++)
		{
    
    
			int a;  //当前选中的节点
			cin >> a;
			if (in[a] != 0)  //如果当前a的入度不为0,不是top
				judge = 0;
					
			for (int k = 0; k < G[a].size(); k++) //更新与当前选中节点有关点的入度
				in[G[a][k]]--;
		}

		if (judge == 0)
			res.push_back(i);
	}

	for (int i = 0; i < res.size(); i++)
	{
    
    
		if (i == 0) cout << res[i];
		else cout << " " << res[i];
	}

	return 0;
}

おすすめ

転載: blog.csdn.net/abyss_miracle/article/details/110563888