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;
}
相关推荐
Dingdangcat8617 分钟前
城市交通多目标检测系统:YOLO11-MAN-FasterCGLU算法优化与实战应用_3
算法·目标检测·目标跟踪
xie_pin_an44 分钟前
深入浅出 C 语言数据结构:从线性表到二叉树的实战指南
c语言·数据结构·图论
tang&1 小时前
滑动窗口:双指针的优雅舞步,征服连续区间问题的利器
数据结构·算法·哈希算法·滑动窗口
拼命鼠鼠1 小时前
【算法】矩阵链乘法的动态规划算法
算法·矩阵·动态规划
LYFlied1 小时前
【每日算法】LeetCode 17. 电话号码的字母组合
前端·算法·leetcode·面试·职场和发展
式5162 小时前
线性代数(八)非齐次方程组的解的结构
线性代数·算法·机器学习
Nandeska2 小时前
2、数据库的索引与底层数据结构
数据结构·数据库
橘颂TA3 小时前
【剑斩OFFER】算法的暴力美学——翻转对
算法·排序算法·结构与算法
叠叠乐3 小时前
robot_state_publisher 参数
java·前端·算法
hweiyu003 小时前
排序算法:冒泡排序
算法·排序算法