label 拓扑排序

题目描述

有N个球,重量从1到N,各不相同,每个球有个编号也是从1到N,各不相同。现在给你一些约束条件,每个约束条件给出数字A,B,表示A号球轻于B号球。请你求出满足约束条件的某个球的重量的全排列,注意如果有多个排列满足条件,我们希望1号球的重量越小越好;当1号球的重量一样时,希望2号球的重量越小越好; 当2号球的重量一样时,希望3号球的重量越小越好......

输入

第一行给出数字N,M,代表有N个球,M个约束条件N (1 ≤ N ≤ 200) , M (0 ≤ M ≤ 40,000).下面将有M行,每行两个数字A,B,(1 ≤ a, b ≤ N)表示A号球轻于B号球。

输出

依次输出从1号球到N号球的重量,任两个数字之间以一个空格格开,无解时输出-1。

样例输入

复制

复制代码
【样例1】
4 1
3 2
【样例2】
6 3
2 4
4 3
4 6
样例输出

复制

复制代码
【样例1】
1 3 2 4
【样例2】
1 2 4 3 5 6
1.拓扑排序(Topological Sorting)

是对**有向无环图(DAG)**的顶点进行线性排序,使得对于图中的每一条有向边 u → v,顶点 u 都排在顶点 v 的前面。

(上次的苹果也是拓扑排序)

2. 算法步骤(Kahn算法)

  1. 初始化

    • 计算每个顶点的入度(指向它的边的数量)。

    • 将入度为 0 的顶点加入队列(或堆)。

  2. 处理队列

    • 取出队首顶点 u,加入拓扑序。priority_queue

    • 遍历 u 的所有邻接顶点 v

      • v 的入度减 1

      • v 的入度变为 0,将其加入队列。

  3. 检查环

    • 若拓扑序的顶点数 ≠ 总顶点数,则图中存在环,无拓扑序。

5. 变种:字典序最小拓扑序

  • 最小堆 :每次选编号最小的入度为 0 的顶点。

  • 最大堆 :每次选编号最大的入度为 0 的顶点(用于反向图)。

"重量序列" 指的是按重量从小到大的顺序排列的球的编号 。例如,若重量 1 对应 3 号球,重量 2 对应 1 号球,重量 3 对应 2 号球,则重量序列为 [3,1,2](即重量 1 是 3 号,重量 2 是 1 号,重量 3 是 2 号)。

"字典序最小" 指的是这个序列在字典排序中最小(类似字典中单词的排序)。例如 [1,2,3][1,3,2] 小,因为第二个位置 2 < 3。

如果用正向拓扑排序(小顶堆选最小编号),得到的是重量序列的字典序最小 。此时++优先保证 "重量从小到大对应的球编号尽可能小",但无法保证 "1 号球的重量尽可能小"。++

"球编号序列" 指的是按球的编号顺序(1→2→...→N)排列的重量 。例如,1 号球的重量是 2,2 号球的重量是 3,3 号球的重量是 1,则编号序列的重量为 [2,3,1](即 1 号重 2,2 号重 3,3 号重 1)。

"球编号序列的重量最小" 指的是按编号顺序,每个位置的重量尽可能小(先保证 1 号最小,再保证 2 号最小,以此类推),这正是题目要求的目标。

deepsleep了

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
int n,m,a,b,ind[210],c[210][210]{0};
int main(){
	cin>>n>>m;
	vector<vector<int>>adj(n+1);
	for(int i=0;i<m;++i){
		cin>>a>>b;
		if(c[a][b])continue;
		c[a][b]=1;
		adj[b].push_back(a);
		ind[a]++;
	}
	priority_queue<int>who;
	for(int i=1;i<=n;++i){
		if(ind[i]==0)who.push(i);
	}
	vector<int>ans;
	while(!who.empty()){
		int x=who.top();
		ans.push_back(x);
		who.pop();
		for(auto i:adj[x]){
			ind[i]--;
			if(ind[i]==0){
				who.push(i);				
			}
		}
	}
	if(ans.size()!=n){
		cout<<"-1";return 0;
	}
	int w[210]{0},x=n;
	for(auto i:ans){
		w[i]=x--;
	}
	for(int i=1;i<=n;++i){
		cout<<w[i]<<" ";
	}
	return 0;
}
相关推荐
while(1){yan}11 小时前
数据结构之链表
数据结构·链表
Han.miracle12 小时前
数据结构——二叉树的从前序与中序遍历序列构造二叉树
java·数据结构·学习·算法·leetcode
mit6.82414 小时前
前后缀分解
算法
独自破碎E15 小时前
判断链表是否为回文
数据结构·链表
你好,我叫C小白15 小时前
C语言 循环结构(1)
c语言·开发语言·算法·while·do...while
寂静山林17 小时前
UVa 10228 A Star not a Tree?
算法
Neverfadeaway18 小时前
【C语言】深入理解函数指针数组应用(4)
c语言·开发语言·算法·回调函数·转移表·c语言实现计算器
Madison-No718 小时前
【C++】探秘vector的底层实现
java·c++·算法
Swift社区19 小时前
LeetCode 401 - 二进制手表
算法·leetcode·ssh
派大星爱吃猫19 小时前
顺序表算法题(LeetCode)
算法·leetcode·职场和发展