Codeforces 1463 E. Plan of Lectures(缩点,拓扑排序)

2024-04-15 23:18

本文主要是介绍Codeforces 1463 E. Plan of Lectures(缩点,拓扑排序),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:
要求你构造一个 n n n的排列,要满足:

  1. a [ i ] a[i] a[i]出现在 i i i之前,如果 a [ i ] = 0 a[i]=0 a[i]=0代表这个数没有限制。仅对条件一保证一定有解。
  2. k k k个特殊对 ( i , j ) (i,j) (i,j),要求满足 i i i在排列中一定在 j j j的左边。

询问是否存在这样的排列。

思路:
这场的 E E E题简单的贪心和模拟就可以解决XD。

  • 假设没有特殊对,那么直接按照条件1的限制跑一次拓扑排序(条件一实际构成了一个DAG图)。
  • 有特殊对后,因为特殊对是要排列在一起的,所以不妨直接并查集缩点。将这些特殊对当做一个点再建图跑拓扑排序。然后对于每个点再按照之前在特殊对中的次序展开
  • 那么咋判断无解的情况呢?因为原本就是一个DAG图,所以新的图中也不应该出现环(出现了就无解)。那么无解就是特殊对构成的次序有环,或者特殊对的次序不满足条件一的限制。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;const int maxn = 3e5 + 7;
int nex[maxn],fa[maxn],deg[maxn];
int cnt,pos[maxn];
vector<int>G[maxn],a,ans;
int findset(int x) {if(fa[x] == x) {return x;}return fa[x] = findset(fa[x]);
}
void Union(int x,int y) {int rx = findset(x),ry = findset(y);if(rx != ry) {fa[ry] = rx;}
}
void bfs(int x) {queue<int>q;q.push(x);ans.push_back(x);while(!q.empty()) {int now = q.front();q.pop();for(int i = 0;i < G[now].size();i++) {int v = G[now][i];deg[v]--;if(deg[v] == 0) {q.push(v);ans.push_back(v);}}}
}int main() {int n,k;scanf("%d%d",&n,&k);int root = 0;for(int i = 1;i <= n;i++) {int x;scanf("%d",&x);fa[i] = i;if(x == 0) root = i;a.push_back(x);}for(int i = 1;i <= k;i++) {int x,y;scanf("%d%d",&x,&y);nex[x] = y;Union(x,y);}for(int i = 1;i <= n;i++) {int x = findset(a[i - 1]),y = findset(i);if(x == y) continue;G[x].push_back(y);deg[y]++;}for(int i = 1;i <= n;i++) {if(i == findset(i)) {cnt++;}}root = findset(root);bfs(root);vector<int>res;for(int i = 0;i < ans.size();i++) {int now = ans[i];for(int j = now;j;j = nex[j]) {res.push_back(j);if(res.size() > n) {printf("0\n");return 0;}}}for(int i = 0;i < res.size();i++) {pos[res[i]] = i;}for(int i = 1;i <= n;i++) {int x = a[i - 1],y = i;if(pos[x] > pos[y]) {printf("0\n");return 0;}}for(int i = 0;i < res.size();i++) {printf("%d ",res[i]);}return 0;
}

本文(可能)同步发布于公众号ACM算法日常
在这里插入图片描述

这篇关于Codeforces 1463 E. Plan of Lectures(缩点,拓扑排序)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907201

相关文章

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m