1093: [ZJOI2007]最大半连通子图

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

  这是一道水题无疑。但是,所谓的半连通确实很能混淆视听。既然题目只针对所谓的“最大半连通子图”,那就依它来吧。
  很明显强连通满足半联通的条件。然后再想,不在同一个强连通分量中,怎样才能做到所谓的“半连通”?
  可能你已经明白了。实在是太简单不过了。找DAG(人称“大哥”)上的一条链足矣。
  而“最大半连通子图拥有的节点数”,即是找缩点后DAG图中拥有最多节点的链。注意,此处并不是找最长链。
  另外,计数?简单。按拓扑序更新即是了。
  但是,但是,但是!
  我第一次交上去WA了。因为,图中有重边。DP更新方案数时很有可能重复计数。
  代码如下:

 1 /**************************************************************
 2     Problem: 1093
 3     User: Doggu
 4     Language: C++
 5     Result: Accepted
 6     Time:1360 ms
 7     Memory:23928 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13
14 template<class T>inline void readin(T &res) {
15     static char ch;T flag=1;
16     while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;
17     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;res*=flag;
18 }
19
20 const int N = 100100;
21 const int M = 1001000;
22 struct Edge {int v,upre;};
23 struct CON {
24     Edge e[M];int head[N], ne;
25     void clear(int p) {ne=p;memset(head,p,sizeof(head));}
26     inline void adde(int u,int v) {e[++ne]=(Edge){v,head[u]};head[u]=ne;}
27 }g,ng;
28
29 int n, m, MOD, u, v;
30 int dfn[N], low[N], idy, stack[N], top, col[N], tcol;
31 int siz[N], f[N], t[N], in[N], vis[N];
32 bool ins[N];
33 void tarjan(int u) {
34     dfn[u]=low[u]=++idy;
35     stack[++top]=u;ins[u]=1;
36     for( int i = g.head[u]; i; i = g.e[i].upre ) {
37         int v=g.e[i].v;
38         if(!dfn[v]) tarjan(v), low[u]=std::min(low[u],low[v]);
39         else if(ins[v]) low[u]=std::min(low[u],dfn[v]);
40     }
41     if(low[u]==dfn[u]) {
42         ++tcol;
43         while(stack[top+1]!=u) {
44             col[stack[top]]=tcol;
45             siz[tcol]++;
46             ins[stack[top--]]=0;
47         }
48     }
49 }
50 inline void add(int &a,int b) {a=a+b>MOD?a+b-MOD:a+b;}
51 int main() {
52     readin(n);readin(m);readin(MOD);
53     g.clear(0);ng.clear(0);
54     for( int i = 1; i <= m; i++ ) {
55         readin(u);readin(v);
56         g.adde(u,v);
57     }
58     for( int i = 1; i <= n; i++ ) if(!dfn[i]) tarjan(i);
59     for( int u = 1; u <= n; u++ ) for( int i = g.head[u]; i; i=g.e[i].upre ) {
60         int v=g.e[i].v;
61         if(col[u]!=col[v]) ng.adde(col[u],col[v]), in[col[v]]++;
62     }
63     top=0;
64     for( int i = 1; i <= tcol; i++ ) if(!in[i]) stack[++top]=i,  f[i]=siz[i], t[i]=1;
65     while(top) {
66         int u=stack[top];top--;
67         for( int i = ng.head[u]; i; i = ng.e[i].upre ) {
68             int v=ng.e[i].v;
69             in[v]--;
70             if(!in[v]) stack[++top]=v;
71             if(vis[v]==u) continue;
72             if(f[u]+siz[v]>f[v]) f[v]=f[u]+siz[v], t[v]=t[u];
73             else if(f[u]+siz[v]==f[v]) add(t[v],t[u]);
74             vis[v]=u;
75         }
76     }
77     int num=0, ans=0;
78     for( int i = 1; i <= tcol; i++ ) num=std::max(num,f[i]);
79     printf("%d\n",num);
80     for( int i = 1; i <= tcol; i++ ) if(f[i]==num) add(ans,t[i]);
81     printf("%d\n",ans);
82     return 0;
83 }
84 

tarjan缩点+拓扑排序简单DP

转载于:https://www.cnblogs.com/Doggu/p/bzoj1093.html

BZOJ 1093 [ZJOI2007]最大半连通子图相关推荐

  1. 解题报告:luogu P2272 [ZJOI2007]最大半连通子图(tarjan缩点、递推DP、hash、set判重)

    这时yxc上课时讲解的截图. 一般用到tarjan算法的题目步骤都非常相似: tarjan算法 缩点,建图(这里要判重) 按照拓扑序递推(这里缩点以后逆向就已经是拓扑序了)/ 循环遍历新图求解答案. ...

  2. BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP

    今天是放假的第一天(不说什么废话了) 什么是半连通子图?就是此图中包含的所有点两两点之间至少有一条单向路径. 题目问了两个问题 1.最大半连通子图的大小 2.最大半连通子图的个数 好了,这个问题看上去 ...

  3. P2272-[ZJOI2007]最大半连通子图【tarjan,缩点】

    正题 题目链接:https://www.luogu.com.cn/problem/P2272 题目大意 半连通图定义为任意两个点(u,v)(u,v)(u,v)满足uuu可以到vvv或vvv可以到uuu ...

  4. tyvj——P3524 最大半连通子图

    P3524 最大半连通子图 时间: 3000ms / 空间: 165536KiB / Java类名: Main 描述 输入格式 第一行包含两个整数N,M,X.N,M分别表示图G的点数与边数,X的意义如 ...

  5. 有向图的强连通分量——最大半联通子图

    最大半联通子图 一个有向图 G=(V,E)G=(V,E)G=(V,E) 称为半连通的 (Semi-Connected),如果满足:∀u,v∈V,满足u→v或v→u∀u,v∈V,满足 u→v 或 v→u ...

  6. java 无向图子图_无向图的连通子图

    /* * CC.h * * Created on: 2014年6月3日 * Author: zhongchao * 计算无向图中的连通分量 */ #ifndef _CC_ #define _CC_ # ...

  7. 数据结构——图:极大小连通子图、图的存储结构、图的遍历

    图的基本概念: 极大连通子图就是连通分量. 极大连通子图与连通分量在无向图(undirected graph)这个前提下是等同的概念. 极小连通子图: 减去任何一条边就不再连通. 不管树还是二叉树:n ...

  8. 获得无向图连通子图_讲透学烂二叉树(一):图的概念和定义—各种属性特征浅析...

    树和图的概念 图是一种特殊的数据结构,由点和边构成,它可以用来描述元素之间的网状关系,这个网状没有顺序,也没有层次,就是简单的把各个元素连接起来. 图的概念和基本性质 图(graph):图(graph ...

  9. Python 计算两个连通子图距离_复杂网络分析之python利器NetworkX

    点击蓝字 关注我们 1 networkx介绍 networkx在2002年5月产生,是一个用Python语言开发的图论与复杂网络建模工具,内置了常用的图与复杂网络分析算法,可以方便的进行复杂网络数据分 ...

最新文章

  1. Python高级函数--map/reduce
  2. 使用PsPing测试Azure虚拟机的连通性
  3. 工信部:今年将发放5G临时牌照,预计下半年5G手机投放市场
  4. SEO站内优化系列讲座(八)——
  5. java se 6u111_linux下查看已经安装的jdk 并卸载jdk
  6. 2018年 第09届 蓝桥杯 Java B组 决赛真题详解及小结
  7. JRebel 启动报错 could not be processed by xxx
  8. ASP.NET的视图(Razor)循环产生html代码
  9. Java通过反射机制修改类中的私有属性的值
  10. linux 适配电脑内核,Linux内核实践 如何添加网络协议[三]:实现 -电脑资料
  11. IE iframe不刷新的问题之完美解决
  12. 阿里的dubbo 到底是用来干嘛的?
  13. 用了这么久的 Chrome,你不会还没掌握这个功能吧?
  14. stream rabbit
  15. 游戏 编程 语言 服务端 客户端 就业
  16. java 图片清晰度_Java 图片处理——如何生成高清晰度而占有磁盘小的缩略图
  17. 混沌数学之Lorenz(洛伦茨)吸引子
  18. springboot2.3.9使用spring data elasticsearch兼容低版本es(6.X)
  19. ros::Rate loop_rate(10); loop_rate.sleep(); 在程序中是休眠到一定时间,并不占用CPU时间
  20. matlab中的颜色设置颜色,matlabpcolor设置颜色

热门文章

  1. numba 让python速度提升百倍
  2. 从尾到头打印单向链表
  3. nginx功能扩展整理
  4. 课堂练习----二维数组
  5. SDUTOJ2779_找朋友(BFS | | DFS双解法)
  6. oracle的用户自定义异常
  7. 欧洲安全研究人员:黑客是如何泄露加密电子邮件
  8. JS合并数组的几种方法及优劣比较
  9. SQL Between a and b
  10. 搭建Python+Django开发环境