Description

  一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

Input

  第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8

Output

  应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

Sample Input

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

Sample Output

3
3
 
正解:tarjan+DP
解题报告:
  遥遥今天讲课讲了这道题,然后感觉这是最水的,就高兴地开了坑,调了半个晚上都没有发现为什么wa了。
  最后发现居然是有重边!!!!!!然后方案重复计算了,但我当时没有马上想出怎么判重,于是看了网上的题解发现可以用set,我真傻真的。
  做法其实挺简单,首先tarjan缩环,然后重构图,可以想到我们一定是在重构的图上选取一条链,使得链的点权和最大。DP可做。
 
 
  1. //It is made by jump~
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <cmath>
  7. #include <algorithm>
  8. #include <ctime>
  9. #include <vector>
  10. #include <queue>
  11. #include <map>
  12. #include <set>
  13. #ifdef WIN32
  14. #define OT "%I64d"
  15. #else
  16. #define OT "%lld"
  17. #endif
  18. using namespace std;
  19. typedef long long LL;
  20. const int MAXN = ;
  21. const int MAXM = ;
  22. int MOD;
  23. int n,m,ecnt,ans,num;
  24. int first[MAXN],to[MAXM],next[MAXM];
  25. bool pd[MAXN];
  26. int dfn[MAXN],low[MAXN];
  27. int Stack[MAXN*],top,belong[MAXN];
  28. int size[MAXN],cnt;
  29. int head[MAXN],ru[MAXN],f[MAXN];
  30. bool vis[MAXN];
  31.  
  32. set<pair<int,int> >bst;//要有一个空格
  33.  
  34. struct edge{
  35. int v,next;
  36. }e[MAXM];
  37.  
  38. inline int getint()
  39. {
  40. int w=,q=;
  41. char c=getchar();
  42. while((c<'' || c>'') && c!='-') c=getchar();
  43. if (c=='-') q=, c=getchar();
  44. while (c>='' && c<='') w=w*+c-'', c=getchar();
  45. return q ? -w : w;
  46. }
  47.  
  48. inline void dfs(int x){
  49. dfn[x]=++ecnt; low[x]=dfn[x];
  50. pd[x]=; Stack[++top]=x;
  51. for(int i=first[x];i;i=next[i]) {
  52. int v=to[i];
  53. if(!dfn[v]) { dfs(v); if(low[v]<low[x]) low[x]=low[v]; }
  54. else if(pd[v]) low[x]=min(low[v],low[x]);
  55. }
  56. if(dfn[x]==low[x]){
  57. cnt++; size[cnt]++; belong[x]=cnt; pd[x]=;
  58. while(Stack[top]!=x&&top) belong[Stack[top]]=cnt,pd[Stack[top]]=,top--,size[cnt]++;
  59. top--;
  60. }
  61. }
  62.  
  63. inline void tarjan(){
  64. ecnt=;
  65. for(int i=;i<=n;i++) if(!dfn[i]) dfs(i);
  66. ecnt=;
  67. for(int i=;i<=n;i++) {
  68. for(int j=first[i];j;j=next[j]) {
  69. int v=to[j];
  70. if(belong[i]!=belong[v]) {
  71. if(bst.find(make_pair(belong[i],belong[v]))!=bst.end()) continue;
  72. e[++ecnt].next=head[belong[i]]; head[belong[i]]=ecnt; e[ecnt].v=belong[v];
  73. ru[belong[v]]++;
  74. bst.insert(make_pair(belong[i],belong[v]));
  75. }
  76. }
  77. }
  78. }
  79.  
  80. inline void DFS(int x){
  81. vis[x]=;
  82. for(int i=head[x];i;i=e[i].next) {
  83. int v=e[i].v;
  84. if(!vis[v]) DFS(v);
  85. if(f[v]>f[x]) f[x]=f[v];
  86. }
  87. f[x]+=size[x];
  88. }
  89.  
  90. inline void DFS2(int x){
  91. vis[x]=;
  92. for(int i=head[x];i;i=e[i].next) {
  93. int v=e[i].v;
  94. if(!vis[v]) DFS2(v);
  95. //不能有重边!!!!!!
  96. if(f[x]==f[v]+size[x]) { dfn[x]+=dfn[v]; if(dfn[x]>=MOD) dfn[x]%=MOD; }
  97. }
  98. if(!head[x]) dfn[x]=;
  99. if(f[x]==ans) { num+=dfn[x]; if(num>=MOD) num%=MOD; }
  100. }
  101.  
  102. inline void DP(){
  103. memset(vis,,sizeof(vis));
  104. for(int i=;i<=cnt;i++) if(!ru[i]) DFS(i),ans=max(ans,f[i]);
  105. memset(vis,,sizeof(vis)); memset(dfn,,sizeof(dfn));
  106. for(int i=;i<=cnt;i++)
  107. if(!ru[i]) {
  108. DFS2(i);
  109. }
  110. printf("%d\n%d",ans,num);
  111. }
  112.  
  113. inline void work(){
  114. n=getint(); m=getint(); MOD=getint();
  115. int x,y;
  116. for(int i=;i<=m;i++) {
  117. x=getint(); y=getint();
  118. next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
  119. }
  120. tarjan();
  121. DP();
  122. }
  123.  
  124. int main()
  125. {
  126. work();
  127. return ;
  128. }

BZOJ1093 最大半连通子图的更多相关文章

  1. BZOJ1093 [ZJOI2007]最大半连通子图

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...

  2. bzoj1093[ZJOI2007]最大半连通子图(tarjan+拓扑排序+dp)

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...

  3. bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...

  4. 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp

    题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...

  5. BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】

    题目 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G ...

  6. BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

    题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...

  7. 【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图

    思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于 ...

  8. 【bzoj1093】 [ZJOI2007]最大半连通子图

    *题目描述: 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路 ...

  9. 最大半连通子图 bzoj 1093

    最大半连通子图 (1.5s 128MB) semi [问题描述] 一个有向图G = (V,E)称为半连通的(Semi-Connected),如果满足:∀ u, v ∈V,满足u->v 或 v - ...

随机推荐

  1. AC日记——逃跑的拉尔夫 codevs 1026 (搜索)

    1026 逃跑的拉尔夫  时间限制: 1 s    空间限制: 128000 KB    题目等级 : 黄金 Gold 题解       题目描述 Description   年轻的拉尔夫开玩笑地从一 ...

  2. aop介绍

  3. windows 80端口被占用

    首先关了iis服务,或者把端口换了. 然后关了SQLServer Reporting Service. http://www.2cto.com/os/201505/399603.html

  4. [转]World Wind Java开发之四——搭建本地WMS服务器

    在提供地理信息系统客户端时,NASA还为用户提供了开源的WMS Server 服务器应用:World Wind WMS Server.利用这个应用,我们可以架设自己的WMS服务并使用自己的数据(也支持 ...

  5. GDB深入研究

    GDB深入研究 一.GDB代码调试 (一)GDB调试实例 在终端中编译一个示例C语言小程序,保存到文件 gdb-sample.c 中,用GCC编译之 #include <stdio.h> ...

  6. Convert和Parse对null值处理的区别

    类型的转换在日常的变成中是经常被用到的,我们最常用的类型转换的方法就是Convert和Parse, 下面来说一下这两者null值处理的区别. int i1 = Convert.ToInt32(null ...

  7. 使用iScroll实现上拉或者下拉刷新

    上拉或者下拉刷新的需求在移动端是非常常见的需求,大部分情况下,实现这个效果都使用网上现有的解决方案,例如有人使用swiper这个插件, 也有人使用iScroll这个滚动插件.本文的示例是利用iscro ...

  8. 斯坦福机器学习实现与分析之八(kmeans算法)

    Kmeans算法简介 作为无监督学习领域的一种简单的算法,Kmeans在实际应用中却是相当广泛的.其过程是通过不断交替迭代求得最优的类中心以及每个样本所属类别,具体步骤如下: 确定类别个数k 随机初始 ...

  9. [vijos1892]树上的最大匹配(树形DP)

    题目:https://vijos.org/p/1892 分析:(100分其实用到各种c++优化,没什么实际意义,所以弄70就可以了) 题目很简单,很容易想出用树形DP,但是求方案数的时候,满满都是细节 ...

  10. 标准I/O

    在程序运行时,会默认为我们打开三个流:标准输入流.标准输出流.标准出错流. 标准输入流一般对应我们的键盘 标准输出流一般对应显示器 标准出错流一般也对应显示器 1.标准输入流 在标准I/O中,java ...