Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 348  Solved: 172
[Submit][Status][Discuss]

Description

【故事背景】
还记得去年JYY所研究的强连通分量的问题吗?去年的题目里,JYY研究了对于有向图的“加边”问题。对于图论有着强烈兴趣的JYY,今年又琢磨起了“删边”的问题。
【问题描述】
对于一个N个点(每个点从1到N编号),M条边的有向图,JYY发现,如果从图中删去一些边,那么原图的连通性会发生改变;而也有一些边,删去之后图的连通性并不会发生改变。
JYY想知道,如果想要使得原图任意两点的连通性保持不变,我们最多能删掉多少条边呢?
为了简化一下大家的工作量,这次JYY保证他给定的有向图一定是一个有向无环图(JYY:大家经过去年的问题,都知道对于给任意有向图的问题,最后都能转化为有向无环图上的问题,所以今年JYY就干脆简化一下大家的工作)。

Input

输入一行包含两个正整数N和M。
接下来M行,每行包含两个1到N之间的正整数x_i和y_i,表示图中存在一条从x_i到y_i的有向边。
输入数据保证,任意两点间只会有至多一条边存在。
N<=30,000,M<=100,000

Output

输出一行包含一个整数,表示JYY最多可以删掉的边数。

Sample Input

5 6
1 2
2 3
3 5
4 5
1 5
1 3

Sample Output

2

HINT

 

Source

 
神题QWQ...
 
首先,一条边$(u,v)$可以删除的条件为:删除这条边后,仍然能从$u$走到$v$
这样的话我们可以贪心处理,对于两个点$(u,v)$,我们保留其最长的路径,其余的全部删去
 
具体实现的时候我们可以先来一边拓扑排序,同时记录下每个点出现的时间,以及该时间入队的点
一个点连出去最长的边一定是包含先访问的点(又是一个贪心)
然而正序处理的话我们并不知道一个点连到的点的联通性
因此我们倒序处理,
联通性用bitset维护
网上的代码都比较神,看了老半天才懂QWQ。。
 
时间复杂度$O(\frac{n*m}{32}$)$
 
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<bitset>
  4. #include<cstring>
  5. #include<queue>
  6. #include<algorithm>
  7. #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
  8. char buf[<<],*p1=buf,*p2=buf;
  9. using namespace std;
  10. const int MAXN=;
  11. inline int read()
  12. {
  13. char c=getchar();int x=,f=;
  14. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  15. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  16. return x*f;
  17. }
  18. struct node
  19. {
  20. int u,v,nxt;
  21. }edge[MAXN*];
  22. int head[MAXN],num=;
  23. inline void AddEdge(int x,int y)
  24. {
  25. edge[num].u=x;
  26. edge[num].v=y;
  27. edge[num].nxt=head[x];
  28. head[x]=num++;
  29. }
  30. int VisitTime[MAXN];//i是第几个入队的
  31. int InputTime[MAXN];//第i个入队的是谁
  32. int inder[MAXN];
  33. bitset<MAXN>can[MAXN];//联通性
  34. int N,M;
  35. int to[MAXN];
  36. int comp(const int &a,const int &b)
  37. {
  38. return VisitTime[a]<VisitTime[b];
  39. }
  40. void Topsort()
  41. {
  42. queue<int>q;
  43. for(int i=;i<=N;i++)
  44. if(inder[i]==) q.push(i);
  45. int tot=;
  46. while(q.size()!=)
  47. {
  48. int p=q.front();q.pop();
  49. InputTime[++tot]=p;
  50. VisitTime[p]=tot;
  51. for(int i=head[p];i!=-;i=edge[i].nxt)
  52. {
  53. inder[edge[i].v]--;
  54. if(inder[edge[i].v]==)
  55. q.push(edge[i].v);
  56. }
  57. }
  58. int ans=;
  59. for(int i=N;i>=;i--)
  60. {
  61. int x=InputTime[i],tot=;
  62. can[x][x]=;
  63. for(int j=head[x];j!=-;j=edge[j].nxt)
  64. to[++tot]=edge[j].v;
  65. sort(to+,to+tot+,comp);
  66. for(int j=;j<=tot;j++)
  67. {
  68. if(can[x][to[j]]) ans++;
  69. else can[x]|=can[to[j]];
  70. }
  71. }
  72. printf("%d",ans);
  73. }
  74. int main()
  75. {
  76. #ifdef WIN32
  77. freopen("a.in","r",stdin);
  78. #endif
  79. memset(head,-,sizeof(head));
  80. N=read(),M=read();
  81. for(int i=;i<=M;i++)
  82. {
  83. int x=read(),y=read();
  84. AddEdge(x,y);
  85. inder[y]++;
  86. }
  87. Topsort();
  88. return ;
  89. }
 

BZOJ4484: [Jsoi2015]最小表示(拓扑排序乱搞+bitset)的更多相关文章

  1. [BZOJ4484][JSOI2015]最小表示[拓扑排序+bitset]

    题意 给你一个 \(n\) 个点 \(m\) 条边的 \(\rm DAG\) ,询问最多能够删除多少条边,使得图的连通性不变 \(n\leq 3\times 10^4\ ,m\leq 10^5\) . ...

  2. BZOJ 4484: [Jsoi2015]最小表示(拓扑排序+bitset)

    传送门 解题思路 \(bitset\)维护连通性,给每个点开个\(bitset\),第\(i\)位为\(1\)则表示与第\(i\)位联通.算答案时显然要枚举每条边,而枚举边的顺序需要贪心,一个点先到达 ...

  3. BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset

    BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i ...

  4. BZOJ4484 JSOI2015最小表示(拓扑排序+bitset)

    考虑在每个点的出边中删除哪些.如果其出边所指向的点中存在某点能到达另一点,那么显然指向被到达点的边是没有用的.于是拓扑排序逆序处理,按拓扑序枚举出边,bitset维护可达点集合即可. #include ...

  5. P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)

    题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...

  6. bzoj4484[JSOI2015]最小表示

    题意 给出一张DAG,要求删除尽量多的边使得连通性不变.(即:若删边前u到v有路径,则删边后仍有路径).点数30000,边数100000. 分析 如果从u到v有(u,v)这条边,且从u到v只有这一条路 ...

  7. HDU 1285 确定比赛名次【字典序最小的拓扑排序 + 优先队列】

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  8. 纯拓扑排序一搞poj2367

    /* author: keyboarder time : 2016-05-18 12:21:26 */ #include<cstdio> #include<string.h> ...

  9. 【拓扑排序】【bitset】Gym - 101128A - Promotions

    给你一张DAG,若选择u点,则必须先选择所有能到达其的点.问你在选择A个点的情况下,哪些点必选:选择B个点的情况下,哪些点必选:选择B个点的情况下,哪些点一定不选. 选择A个点的情况,必选的点是那些其 ...

随机推荐

  1. JavaScript 对象(上)

    简述: 1.是 JavaScript 的基本类型 2.是一种复合值,可通过名字访问这些值 3.可看作属性的无序集合,每个属性都是一个名/值对(属性名是字符串或标识符) 4.可以从一个称为原型的对象继承 ...

  2. Redis学习笔记之延时队列

    目录 一.业务场景 二.Redis延时队列 一.业务场景 所谓延时队列就是延时的消息队列,下面说一下一些业务场景比较好理解 1.1 实践场景 订单支付失败,每隔一段时间提醒用户 用户并发量的情况,可以 ...

  3. springboot集成quartz定时任务课动态执行

    <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</ ...

  4. TypeScript基础类型,类实例和函数类型声明

    TypeScript(TS)是微软研发的编程语言,是JavaScript的超集,也就是在JavaScript的基础上添加了一些特性.其中之一就是类型声明. 一.基础类型 TS的基础类型有 Boolea ...

  5. jenkins 'cordova' command not recognised on Jenkins Windows slave

    在jenkins里构建ionic项目.在构建Execute Windows bath command 执行 cordova 跟ionic 命令失败.但是运行cmd却能够执行成功. 惊不惊喜 意不意外, ...

  6. 五款实用免费的Python机器学习集成开发环境(5 free Python IDE for Machine Learning)(图文详解)

    前言 集成开发环境(IDE)是提供给程序员和开发者的一种基本应用,用来编写和测试软件.一般而言,IDE 由一个编辑器,一个编译器(或称之为解释器),和一个调试器组成,通常能够通过 GUI(图形界面)来 ...

  7. java jar 后台运行

    nohup java -jar $APP_NAME.jar >/dev/null &

  8. Dependency injection in .NET Core的最佳实践

    我们知道依赖注入(DI)是一种实现对象及其协作者或依赖关系之间松散耦合的技术. ASP.NET Core包含一个简单的内建容器来支持构造器注入. 我们试图将DI的最佳实践带到.NET Core应用程序 ...

  9. 分析 Oracle SQL 执行计划的关注点

    本文内容摘自<剑破冰山--Oracle开发艺术>一书. 1.判定主要矛盾 在遇到复杂 SQL 语句时,执行计划也非常复杂,往往让人分析起来觉得无从下手,此时应避免顺序解决问题,而是快速定位 ...

  10. systemctl enable docker.service

    [root@dingyingsi ~]# systemctl start docker.service [root@dingyingsi ~]# systemctl enable docker.ser ...