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;
}
相关推荐
机器人零零壹16 小时前
技术白皮书:iRobotCAM如何解决机器人激光切割应用中的核心难点,从CAD离线编程到双目视觉定位与轨迹自适应提升复杂空间曲线切割的精度、效率与柔性化水平
人工智能·算法
ZhengEnCi19 小时前
大模型的分类到底怎么分:从基础模型到推理模型、从通用到专用的完整图谱
算法
取名真是20 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
罗西的思考20 小时前
【轻量化复刻大模型 / KIMI K3】KDA 模块交互式演示
人工智能·算法·机器学习
nm_zfyjt1 天前
信息流广告投放优化实践:线索成本评估模型与转化链路重构(家装建材案例)
算法·重构·内蒙古朋友圈广告服务商·内蒙古朋友圈获客
w_zero_one1 天前
算法--构造
java·数据结构·算法
其实防守也摸鱼1 天前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php
小超人诞生日记1 天前
C++ 智能指针的使用及其原理详解
c++·算法
lisw051 天前
互联网上的数据结构可视化!
数据结构·信息可视化