最大半连通子图

【问题描述】

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

若满足,则称G’是G的一个导出子图。

若G’是G的导出子图,且G’半连通,则称G’为G的半连通子图。

若G’是G所有半连通子图中包含节点数最多的,则称G’是G的最大半连通子图。

给定一个有向图G,请求出G的最大半连通子图拥有的节点数K,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

【输入文件】

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

【输出文件】

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

【样例输入】

6 6 20070603

1 2

2 1

1 3

2 4

5 6

6 4

【样例输出】

3

3

【数据规模】

对于20%的数据, N ≤ 18;

对于60%的数据, N ≤ 10000;

对于100%的数据, N ≤ 100000, M ≤ 1000000;

对于100%的数据, X ≤ 108


题解:

首先用Tarjon缩点,去重连边,得到新图,那么题目就变成了求图中最长链及最长链个数

最长链可以直接用拓扑排序

最长链个数用一个类似递推的方法

记录每一个点的方案数

那么当前点的方案数就等于连到此点且满足距离相等的点的方案数之和

最后查找距离等于最长链的点,答案为它们的方案数之和

 #include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
inline int Get()
{
int x = ;
char c = getchar();
while('' > c || c > '') c = getchar();
while('' <= c && c <= '')
{
x = (x << ) + (x << ) + c - '';
c = getchar();
}
return x;
}
const int me = ;
int n, m, mo;
int x[me], y[me];
int tot;
int de[me], to[me], fir[me], nex[me];
int ue[me];
int si[me];
inline void Ins(int x, int y)
{
nex[++tot] = fir[x];
fir[x] = tot;
to[tot] = y;
}
int num, top, col;
int ti[me], lo[me], st[me], co[me];
inline void Tarjan(int u)
{
ti[u] = lo[u] = ++num;
st[++top] = u;
for(int i = fir[u]; i; i = nex[i])
{
int v = to[i];
if(!ti[v])
{
Tarjan(v);
lo[u] = min(lo[u], lo[v]);
}
else
if(!co[v])
lo[u] = min(lo[u], ti[v]);
}
if(lo[u] == ti[u])
{
co[u] = ++col;
++si[col];
while(st[top] != u)
{
++si[col];
co[st[top]] = col;
--top;
}
--top;
}
}
int t, w;
int ans;
int e[me];
int dis[me];
inline bool rule(int a, int b)
{
if(x[a] != x[b]) return x[a] < x[b];
return y[a] < y[b];
}
int nu[me];
inline void Remove()
{
for(int i = ; i <= m; ++i)
{
nu[i] = i;
x[i] = co[x[i]];
y[i] = co[y[i]];
}
sort(nu + , nu + + m, rule);
}
inline void Build()
{
tot = ;
memset(fir, , sizeof(fir));
for(int i = ; i <= m; ++i)
{
int z = nu[i];
if((x[z] != y[z]) && (x[z] != x[nu[i - ]] || y[z] != y[nu[i - ]]))
{
++de[y[z]];
Ins(x[z], y[z]);
}
}
}
inline void Reset()
{
for(int i = ; i <= col; ++i)
if(!de[i])
{
ue[++w] = i;
dis[i] = si[i];
e[i] = ;
if(dis[ans] < dis[i]) ans = i;
}
}
inline void Topo()
{
while(t < w)
{
int u = ue[++t];
for(int i = fir[u]; i; i = nex[i])
{
int v = to[i];
--de[v];
if(dis[v] < dis[u] + si[v])
{
dis[v] = dis[u] + si[v];
e[v] = ;
if(dis[ans] < dis[v]) ans = v;
}
if(dis[v] == dis[u] + si[v])
e[v] = (e[v] + e[u]) % mo;
if(!de[v]) ue[++w] = v;
}
}
}
int anss;
inline void Ask()
{
for(int i = ; i <= n; ++i)
if(dis[i] == dis[ans])
anss = (anss + e[i]) % mo;
}
int main()
{
n = Get(), m = Get(), mo = Get();
for(int i = ; i <= m; ++i)
{
x[i] = Get(), y[i] = Get();
Ins(x[i], y[i]);
}
for(int i = ; i <= n; ++i)
if(!ti[i])
Tarjan(i);
Remove();
Build();
Reset();
Topo();
Ask();
printf("%d\n%d", dis[ans], anss);
}

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

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

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

  2. bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划

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

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

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

  4. bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)

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

  5. BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )

    WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...

  6. BZOJ 1093 最大半连通子图 题解

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2767  Solved: 1095[Submit][S ...

  7. [BZOJ]1093 最大半连通子图(ZJOI2007)

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

  8. 【刷题】BZOJ 1093 [ZJOI2007]最大半连通子图

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

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

随机推荐

  1. .NET Core 2016 回顾

    都在回顾自己的2016,今天我们来看看.NET Core的2016. 每一年的脚步的确是快,转眼间马上就2017.新的一年,带着理想和抱负继续出发. 1 月 ASP.NET 5 改名 ASP.NET ...

  2. 常用 meta 整理

    <!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --> <meta name="HandheldFriendly" con ...

  3. SharePoint2016安装的过程的”Microsoft.SharePoint.Upgrade.SPUpgradeException”错误解决方法

    前提 在windows server 2012的服务器上运行安装sharepoint2016出现如下错误: Could not load file or assembly ‘Microsoft.Dat ...

  4. Joshua Bloch错了? ——适当改变你的Builder模式实现

    注:这一系列都是小品文.它们偏重的并不是如何实现模式,而是一系列在模式实现,使用等众多方面绝对值得思考的问题.如果您仅仅希望知道一个模式该如何实现,那么整个系列都会让您失望.如果您希望更深入地了解各个 ...

  5. 2000条你应知的WPF小姿势 基础篇<34-39 Unhandled Exceptions和Resource>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  6. 死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?

    写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中, ...

  7. SQL Server 服务器磁盘测试之SQLIO篇(二)

    上次放出了一篇文章,针对磁盘卷簇大小默认4KB和自定义64KB进行了测试,测试内容为随机和顺序读写,大小为8KB和64KB,有人觉得这并没有照顾到SQL Server所有的IO使用情景.这篇测试文章, ...

  8. Java 8函数编程轻松入门(四)方法引用

    C#中系统提供了许多IEnumerable的扩展方法.同样在Java 8中新引入了Collector类. 1.方法引用 定义: 简而言之:就是一个Lambda表达式.在Java 8中,我们我们会使用L ...

  9. rsync 笔记之 list

    通过 rsync --list-only 可以列出可用的 文件/目录或者 module 下面两者的含义是完全不同的: rsync --list-only root@192.168.4.140: 使用系 ...

  10. MailKit---状态更改和删除

    当我们拉取邮件列表,并展示邮件后需要打开邮件,同时标识本邮件状态为已读状态,或者我们直接删除邮件.下面介绍基本的应用. 首先了解邮件的所有枚举状态:MailKit.MessageFlags包括:(No ...