题目链接G题

题意

序列 \(a_1,a_2,⋯,a_n\) 是一个排列, 当且仅当它含有 1 到 n 的所有整数。

排列 \(a_1,a_2,⋯,a_n\) 是一个有向图的拓扑排序,当且仅当对于每条边 \(u→v\),这个排列中 \(u\) 都出现在 \(v\) 之前。

给定一个有向无环图,添加至多 k 条有向边,使图保持无环,且字典序最小的拓扑排序字典序最大

思路

很有意思的一道构造题。

主要想法就是字典序较大的连边限制字典序小的。

两个堆:一个小根一个大根(小根堆是当前可以填写的节点集合,大根堆是已经分配了入边的集合)

拓扑序中,要填x,如果不填x,将要填的后面一个更大,(意味着不填x更优)那么将k条边中一条分配给x,入大根堆。但是还有一些不能入的情况:

如果 k为0 或者 小根堆siz=1 且 大根堆空或大根堆最大小于x,那么把x放入拓扑序,否则放到大根堆;

reason:k为0,没有边可以分配了

小根堆siz=1,是当前最后一个入度为0的点,如果加入边会出现环

如果是当前最后一个入度为0的点且没有点被加边,那么加边就是浪费,不如直接拓扑

如果是当前最后一个入度为0的点且比所有被加边的编号都要大,也是浪费(

如果小根堆空,那么把大根堆top放入拓扑序并且和拓扑序前一个连入边.

当一个点被放入拓扑序的时候,把所有指向的点入度--,如果为0,那么入小根堆。

这样就构成了一个系统:小根堆是可以放的点,大根堆是预备了一条边,但是不知道pre是谁的点。显然从任意一个点连边都是合法的。那么当不得不把这个点放进拓扑序的时候就选择其中最大的节点pop就好了(在前面的尽可能大)

(不知道为啥这道题过不了样例就AC……样例奇怪得很)

(注:如果你WA on test1了,把文件头加上再试一遍))

Code

采用set替代堆。

#include <bits/stdc++.h>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=1e5+10;
set<int>pmax,pmin;
vector<pair<int,int> >edge;
vector<int>g[N];
int in[N],ord[N],n,m,k,cnt,pre; void topo( int x )
{
ord[++cnt]=x; pre=x;
for ( int i=g[x].size()-1; ~i; i-- )
{
int y=g[x][i];
if ( --in[y]==0 ) pmin.insert(y);
}
} int main()
{
freopen( "graph.in","r",stdin ); freopen( "graph.out","w",stdout ); scanf( "%d%d%d",&n,&m,&k );
for ( int i=1; i<=n; i++ )
g[i].clear(),in[i]=0;
for ( int i=1,u,v; i<=m; i++ )
scanf( "%d%d",&u,&v ),g[u].push_back(v),in[v]++; pmin.clear(); pmax.clear(); edge.clear();
for ( int i=1; i<=n; i++ )
if ( in[i]==0 ) pmin.insert(i);
pre=0; cnt=0;
while ( cnt<n )
{
if ( pmin.size()==0 ) //如果小根堆空,那么把大根堆top放入拓扑序并且和拓扑序前一个连入边
{
int x=*--pmax.end();
edge.push_back( mp(pre,x) );
topo(x); pmax.erase(x);
}
else if ( !k || pmin.size()==1 && (pmax.size()==0 || *pmin.begin()>*--pmax.end()) )
{
int x=*pmin.begin(); topo(x); pmin.erase(x);
} //如果 k为0 或者 小根堆=1 且 大根堆空或大根堆最大小于x,那么把x放入拓扑序
else //否则放入大根堆
{
k--; int x=*pmin.begin();
pmin.erase(x); pmax.insert(x);
}
}
for ( int i=1; i<=cnt; i++ )
printf( "%d ",ord[i] );
printf( "\n%d\n",edge.size() );
for ( int i=0; i<edge.size(); i++ )
printf( "%d %d\n",edge[i].first,edge[i].second );
}

【题解】G.Graph(2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest)的更多相关文章

  1. Codeforces 2018-2019 ICPC, NEERC, Southern Subregional Contest

    2018-2019 ICPC, NEERC, Southern Subregional Contest 闲谈: 被操哥和男神带飞的一场ACM,第一把做了这么多题,荣幸成为7题队,虽然比赛的时候频频出锅 ...

  2. 2018-2019 ICPC, NEERC, Southern Subregional Contest

    目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Clou ...

  3. 模拟赛小结:2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest

    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest 2019年10月11日 15:35-20:35(Solved 8,Penalty 675 ...

  4. 2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest (9/12)

    $$2015-2016\ ACM-ICPC,\ NEERC,\ Northern\ Subregional\ Contest$$ \(A.Alex\ Origami\ Squares\) 签到 //# ...

  5. 【2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest D】---暑假三校训练

    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest D Problem D. Distribution in Metagonia Input ...

  6. ACM ICPC 2016–2017, NEERC, Northern Subregional Contest Problem J. Java2016

    题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229510 时间限制:2s 空间限制:256MB 题目大意: 给定一个数字c 用 " ...

  7. codeforce1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) 题解

    秉承ACM团队合作的思想懒,这篇blog只有部分题解,剩余的请前往星感大神Star_Feel的blog食用(表示男神汉克斯更懒不屑于写我们分别代写了下...) C. Cloud Computing 扫 ...

  8. 2016 NEERC, Northern Subregional Contest G.Gangsters in Central City(LCA)

    G.Gangsters in Central City 题意:一棵树,节点1为根,是水源.水顺着边流至叶子.该树的每个叶子上有房子.有q个询问,一种为房子u被强盗入侵,另一种为强盗撤离房子u.对于每个 ...

  9. Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结

    第一次打ACM比赛,和yyf两个人一起搞事情 感觉被两个学长队暴打的好惨啊 然后我一直做傻子题,yyf一直在切神仙题 然后放一波题解(部分) A. Find a Number LINK 题目大意 给你 ...

随机推荐

  1. TypeError: Cannot read property 'Component' of undefined

    继续跟着阮一峰的教程走,下面写到PropTypes的getDefaultProps时,又出现了问题,基于上一个createClass的报错换成了Component写法 错误描述: 解决方法:引入rea ...

  2. bluestore的osd自启动

    前言 自启动相关的文章很多,有分析的很详细的文章,这里就不做赘述,本篇讲述的是什么情况下用,怎么用的问题 使用场景 一台机器的系统盘坏了,需要重装系统,相关的一些信息没有了,但是上面的数据盘还是在的, ...

  3. [LeetCode题解]19. 删除链表的倒数第N个节点 | 双指针 + 一次遍历

    解题思路 双指针:第一个指针先走 n 步,然后两个指针同时走. 这里要注意当链表长度<=n,要删除头节点. 代码 /** * Definition for singly-linked list. ...

  4. 想换4K显示器了?那你搞懂啥是4K了吗?

    前言 我们在科技资讯以及电脑显示器.数字电视等电子产品的宣传语中,经常能够看见4K的字样.最近,B站(哔哩哔哩)升级了HTML5播放器和视频云等相关服务,为广大用户提供了超高清(UHD: Ultra ...

  5. C++深拷贝与浅拷贝区别

    浅拷贝只是对指针的拷贝,浅拷贝后两个指针指向同一个内存空间: 深拷贝不仅对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针. 当对一个已知对象进行拷贝时,编译系统会 ...

  6. 使用python统计《三国演义》小说里人物出现次数前十名,并实现可视化。

    一.安装所需要的第三方库 jieba (jieba是优秀的中文分词第三分库) pyecharts (一个优秀的数据可视化库) <三国演义>.txt下载地址(提取码:kist ) 使用pyc ...

  7. 关于Java集合框架,这篇讲的还算不错了,建议大家看看!

    集合框架 为什么要用集合而非数组: 虽然数组是保存一组对象最有效的方式,但是数组具有固定尺寸,但在写程序时并不知道将需要多少个对象.而集合能够自动地调整自己的尺寸. 打印数组时,必须使用Arrays. ...

  8. 如何用FL Studio做电音

    电音制作,自然少不了适合做电音的软件,市面上可以进行电音制作的软件不少,可是如果在这些软件中只能选择一款的话,想必多数人会把票投给FL Studio,毕竟高效率是永远不变的真理,今天就让我们来看看如何 ...

  9. 用思维导图软件iMindMap来提高记忆

    虽说人的大脑是强大的存储器,但是我们终究没有挖掘出大脑全部的潜能,在记忆时或许因为方式.或许是干扰因素都能够影响我们的记忆力,致使有心无力,快来让思维导图来拯救你的记忆吧. 记忆是经验的关键,思维导图 ...

  10. 图像分割必备知识点 | Unet详解 理论+ 代码

    文章转自:微信公众号[机器学习炼丹术].文章转载或者交流联系作者微信:cyx645016617 喜欢的话可以参与文中的讨论.在文章末尾点赞.在看点一下呗. 0 概述 语义分割(Semantic Seg ...