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缩点,因为强连通分量必然能放在一个半连通子图里。
之后图变为DAG 拓扑排序dp即可。
f[i]表示到i的最大半连通子图,sl[i]表示i这个强连通分量的点数,sum[i]表示方案数%k。
f[v]=max(f[u]+sl[v])u为所有能到达v的点。
sum[v]=sigema(sum[u])f[u]+sl[v]==f[v]
这里要注意,两点间可能有重边,要做判断防止一个点被加两遍。
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. struct X
  6. {
  7. int v,n,f;
  8. }x[],y[];
  9. const int N=1e5+;
  10. int s,st[N],top,dfn[N],low[N],pa[N],cnt,t,w=-,q[N],syg[N];
  11. bool vis[N],sf[N];
  12. void add(int u,int v)
  13. {
  14. y[++s].n=y[u].f;
  15. y[y[u].f=s].v=v;
  16. }
  17. void dfs(int u)
  18. {
  19. dfn[u]=low[u]=++s;
  20. vis[st[++top]=u]=sf[u]=;
  21. for(int i=x[u].f;i;i=x[i].n)
  22. if(!vis[x[i].v]) dfs(x[i].v),low[u]=min(low[x[i].v],low[u]);
  23. else if(sf[x[i].v]) low[u]=min(low[u],dfn[x[i].v]);
  24. if(dfn[u]==low[u])
  25. {
  26. pa[u]=++cnt;
  27. for(;st[top]!=u;top--)
  28. pa[st[top]]=cnt,sf[st[top]]=;
  29. top--;sf[u]=;
  30. }
  31. }
  32. int main()
  33. {
  34. int n,m,mod;
  35. scanf("%d%d%d",&n,&m,&mod);
  36. for(int i=;i<=m;i++)
  37. {
  38. int u;
  39. scanf("%d%d",&u,&x[i].v);
  40. x[i].n=x[u].f;
  41. x[u].f=i;
  42. }
  43. for(int i=;i<=n;i++)
  44. if(!vis[i]) dfs(i);
  45. memset(st,,sizeof(st));
  46. memset(dfn,,sizeof(dfn));
  47. memset(vis,,sizeof(vis));
  48. s=;
  49. for(int i=;i<=n;i++)
  50. {
  51. st[pa[i]]++;
  52. for(int j=x[i].f;j;j=x[j].n)
  53. if(pa[i]!=pa[x[j].v]) add(pa[i],pa[x[j].v]),++dfn[pa[x[j].v]];
  54. }
  55. memset(pa,,sizeof(pa));
  56. memset(low,,sizeof(low));
  57. for(int i=;i<=cnt;i++)
  58. if(!dfn[i]) vis[q[++w]=i]=,low[i]=,pa[i]=st[i];
  59. for(;t<=w;t++)
  60. {
  61. for(int i=y[q[t]].f;i;i=y[i].n)
  62. if(!vis[y[i].v])
  63. {
  64. dfn[y[i].v]--;
  65. if(!dfn[y[i].v]) vis[q[++w]=y[i].v]=;
  66. if(syg[y[i].v]==q[t]) continue;
  67. syg[y[i].v]=q[t];
  68. if(st[y[i].v]+pa[q[t]]>pa[y[i].v])
  69. {
  70. pa[y[i].v]=pa[q[t]]+st[y[i].v];
  71. low[y[i].v]=low[q[t]];
  72. }
  73. else if(st[y[i].v]+pa[q[t]]==pa[y[i].v]) low[y[i].v]+=low[q[t]],low[y[i].v]%=mod;
  74. }
  75. }
  76. int ans1=,ans2;
  77. for(int i=;i<=cnt;i++)
  78. if(ans1<pa[i]) ans1=pa[i],ans2=low[i];
  79. else if(ans1==pa[i]) ans2+=low[i],ans2%=mod;
  80. printf("%d\n%d",ans1,ans2);
  81. return ;
  82. }

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

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

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

  2. 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 ...

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

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

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

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

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

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

  6. BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)

    发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...

  7. 2018.11.06 bzoj1093: [ZJOI2007]最大半连通子图(缩点+拓扑排序)

    传送门 先将原图缩点,缩掉之后的点权就是连通块大小. 然后用拓扑排序统计最长链数就行了. 自己yyyyyy了一下一个好一点的统计方法. 把所有缩了之后的点都连向一个虚点. 然后再跑拓扑,这样最后虚点的 ...

  8. BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)

    题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ...

  9. BZOJ 1093 [ZJOI2007]最大半连通子图

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1986  Solved: 802[Submit][St ...

随机推荐

  1. 关于语句#ifdef OS_GLOBALS #define OS_EXT #else #define OS_EXT extern #endif 的说明

    声明全局变量使用的技术——摘自uC/OS-II中文版 以下是如何定义全局 变量.众所周知,全局变量应该是得到内存分配且可以被其他模块通过C 语言中extern 关键字调用的变量.因此,必须在 .C 和 ...

  2. 坑的可以呀re

    .findall()   直接匹配字母和数字 元字符:. ^ $ * + ? {} [] () \ import re print(re.findall("alex"," ...

  3. Vs2015智能提示英文?

    Vs2015智能提示英文? 装了vs2015代码的智能提示全部变成英文了   找到这个目录 C:\Program Files (x86)\Reference Assemblies\Microsoft\ ...

  4. Flask最佳实践

    https://zhuanlan.zhihu.com/p/22774028?refer=python-cn

  5. Centos6.4 aria2 webui-aria2

    wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm rpm -ivh ...

  6. R&S学习笔记(二)

    1.OSPF:路由条目1万多条.收敛时间1s:ISIS:路由条目可以达2万多条,收敛时间50ms().ISIS在链路层上面,不依赖IP这层,这样给了它很多可能.比如IPv4, IPv6路由的混合承载, ...

  7. 安装了多个Oracle11g的客户端,哪个客户端的tnsnames.ora会起作用?

    如果我们由于需要安装了多个Oracle的client,哪个客户端的tnsnames.ora会起作用呢? 答案是: 在安装好clinent端后,安装程序会把client的bin目录放到path里面,pa ...

  8. 天地图应用ArcGIS发布的服务

    本文包含三个部分:利用ArcMap将Excel的数据转化为ArcGIS MXD文件.利用ArcMap发布服务.天地图添加ArcGIS发布的服务. 一 MXD文件的生成 假设在Excel中存有两个点的坐 ...

  9. JSON.parse

    摘自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse The J ...

  10. java 获取当月第一天和最后一天 获取前一个月第一天和最后一天

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");                    //获取前月的第一 ...