小C图

来源:互联网 发布:linux文件分别打包命令 编辑:程序博客网 时间:2024/05/16 08:38

题目描述

C 非常喜欢图论,他想出了一张 N 个点 M 条边的有向图,其中点记为 1…N,边记为 1…M。

C 觉得一张没有环的并且边的编号连续的图是完美的,他称之为小 C 图,现在,他希望你能在这张有向图上,找出最少的小 C 图使得这些小 C 图能够包含所有边。为了检验你确实找出了所有的小 C 图,你需要把每张小 C 图包含的边的编号区间输出。

输入格式

输入的第一行有两个整数 N,M。
接下来 M 行,每行两个整数 X,Y,第 i 行代表编号为 i 的边可以从 X 通向 Y。

输出格式:

输出的第一行一个整数 answer 代表能找出的小 C 图的最少数量。
接下来 answer 行,每行两个正整数,按照升序输出第 i 张小 C 图包含的边的区间。
若有多组解则输出第 1 张小 C 图右端点最大的解,若仍有多组解则输出第 2 张小 C 图右端点最大的解,依次类推。

样例输入:

5 4
1 2
2 3
3 4
4 5

样例输出:

1
1 4
数据范围: 对于 30%的数据,n<=1000,m<= 7000,
对于 60%的数据,保证数据随机,
对于 100%的数据,n<=100000,m<=300000,保证无自环.
【题目讲解】
我一开始做这道题,反正是理解错题意了的,导致一直都没想出来。。。

这道题题意大概就是说,它给你一系列的边,要你建一种图,这种图可以分为很多个(并且这种图的每条边可以不连续,也就是说不一定要相连),每个图的边的编号(每条边输进来的顺序)要是连续的,并且该图不能存在环!然后题目要求输出小C图的总个数,并且把每个小C图的边包含的区间输出来。

显然这题是贪心,因为每条边都要覆盖到,我们可以找到从第一个点开始的最长区间,然后从区间右端点开始重新找。
基于这个思想,我们就可以暴力做了,枚举边,用拓扑或者 tarjan 判环。
时间复杂度:O(nm),空间复杂度:O(m),期望得分:30 分。

然而实际上我们并不需要枚举每条边,二分一下答案,暴力判环就好了,然而实际上是会被卡掉的,由于数据随机,这种方法是可以过的。
时间复杂度:O(mnlogm),空间复杂度:O(m),期望得分:60 分。

发现二分的局限性在于每条边被扫过不止一次,考虑一种更优的方法使得每条边只被扫过一次,考虑先倍增找出最长区间长度所在的区间,再二分+判环。
(这里二分加判环,是因为我们在做倍增的时候,会有两个小的区间,得到一个大区间,但有可能是前一个小区间满足条件,而后一个小区间不满足条件,但第二个区间有部分加到前一个小区间中也会满足条件,于是这里要二分并且要判环,当时我是没懂)
时间复杂度:O(mlogm+nlogm),空间复杂度:O(m),期望得分:100 分。

以上是出题人给的解析(本蘜加了点修改)

源代码

原创粉丝点击