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]
这里要注意,两点间可能有重边,要做判断防止一个点被加两遍。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct X
{
int v,n,f;
}x[],y[];
const int N=1e5+;
int s,st[N],top,dfn[N],low[N],pa[N],cnt,t,w=-,q[N],syg[N];
bool vis[N],sf[N];
void add(int u,int v)
{
y[++s].n=y[u].f;
y[y[u].f=s].v=v;
}
void dfs(int u)
{
dfn[u]=low[u]=++s;
vis[st[++top]=u]=sf[u]=;
for(int i=x[u].f;i;i=x[i].n)
if(!vis[x[i].v]) dfs(x[i].v),low[u]=min(low[x[i].v],low[u]);
else if(sf[x[i].v]) low[u]=min(low[u],dfn[x[i].v]);
if(dfn[u]==low[u])
{
pa[u]=++cnt;
for(;st[top]!=u;top--)
pa[st[top]]=cnt,sf[st[top]]=;
top--;sf[u]=;
}
}
int main()
{
int n,m,mod;
scanf("%d%d%d",&n,&m,&mod);
for(int i=;i<=m;i++)
{
int u;
scanf("%d%d",&u,&x[i].v);
x[i].n=x[u].f;
x[u].f=i;
}
for(int i=;i<=n;i++)
if(!vis[i]) dfs(i);
memset(st,,sizeof(st));
memset(dfn,,sizeof(dfn));
memset(vis,,sizeof(vis));
s=;
for(int i=;i<=n;i++)
{
st[pa[i]]++;
for(int j=x[i].f;j;j=x[j].n)
if(pa[i]!=pa[x[j].v]) add(pa[i],pa[x[j].v]),++dfn[pa[x[j].v]];
}
memset(pa,,sizeof(pa));
memset(low,,sizeof(low));
for(int i=;i<=cnt;i++)
if(!dfn[i]) vis[q[++w]=i]=,low[i]=,pa[i]=st[i];
for(;t<=w;t++)
{
for(int i=y[q[t]].f;i;i=y[i].n)
if(!vis[y[i].v])
{
dfn[y[i].v]--;
if(!dfn[y[i].v]) vis[q[++w]=y[i].v]=;
if(syg[y[i].v]==q[t]) continue;
syg[y[i].v]=q[t];
if(st[y[i].v]+pa[q[t]]>pa[y[i].v])
{
pa[y[i].v]=pa[q[t]]+st[y[i].v];
low[y[i].v]=low[q[t]];
}
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;
}
}
int ans1=,ans2;
for(int i=;i<=cnt;i++)
if(ans1<pa[i]) ans1=pa[i],ans2=low[i];
else if(ans1==pa[i]) ans2+=low[i],ans2%=mod;
printf("%d\n%d",ans1,ans2);
return ;
}

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. Microsoft JScript 运行时错误: '$' 未定义

    在运行MVC Music Store时Visual Studio 捕捉到此错误: Microsoft JScript 运行时错误: '$' 未定义 可能是引用的Scripts 引用出错,检查当前文件中 ...

  2. ubuntu16041,安装opencv3.1.0

    [非常感谢:http://www.linuxdiyf.com/linux/18482.html] 1.依赖关系: sudo apt-get install build-essentialsudo ap ...

  3. Gradle脚本基础全攻略

    http://blog.csdn.net/yanbober/article/details/49314255

  4. 69 个经典 Spring 面试题和答案

    Spring 概述 什么是spring?Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标 ...

  5. AttributeError: 'list' object has no attribute 'write_pdf'

    我在可视化决策树,运行以下代码时报错:AttributeError: 'list' object has no attribute 'write_pdf' 我使用的是python3.4 from sk ...

  6. tornado api 简单模板

    # 安装 pip insatll tornado # 主文件 web_server.py #!/usr/bin/env python # encoding: utf-8 import tornado. ...

  7. 同时闪烁多个要素代码(ArcEngine)

    /// <summary> /// 根据查询条件构造/// </summary> /// <param name="where">查询条件< ...

  8. BASH 漏洞修复

    Red Hat在Bash Shell中发现了一个名为Bash Bug的安全漏洞,当用户正常访问时,该漏洞允许攻击者的代码像在Shell中一样执行,这样就为各种各样的攻击打开了方便之门.据悉,其严重性要 ...

  9. C++注意

    断言assert是仅在Debug版本起作用的宏,它用于检查“不应该”发生的情况. 在函数的入口处,使用断言检查参数的有效性(合法性). 如果程序在assert处终止了,并不是说含有该assert的函数 ...

  10. Asprise-OCR的使用

    Asprise-OCR下载地址: http://asprise.com/product/ocr/download.php?lang=csharp 其中需要使用的3个dll是AspriseOCR.dll ...