[BZOJ]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)不会出现两次。
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
HINT
N ≤10000, M ≤1000000,X ≤10^8。
Solution
拿到这题,我们首先思考半连通分量是个什么东西。
首先我们知道,强连通分量一定是半连通分量,
题目要求我们求最大的半连通分量,所以如果选取了一个强连通分量里的点,那么把该点所在的整个强连通分量都选进去肯定没问题,选取一个强连通分量和选取一个点是等价的。
所以我们很自然地用tarjan缩了缩点……
然后我们得到了一个带点权的拓扑图。
仔细一想,我们发现拓扑图中的半连通分量是一条链,
所以问题也就变成了找拓扑图中的最长链,并统计最长链的条数。
(这个用DP不会做你退群吧)
注意缩点之后要处理掉重边。时间复杂度O(n+m)。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MN 100005
#define MM 1000005
using namespace std;
struct edge{int nex,to;}e[MM];
struct bian{int x,y;}b[MM];
bool u[MN],ink[MN];
int low[MN],st[MN],hr[MN],bel[MN],w[MN],d[MN],q[MN],f1[MN],f2[MN];
int dfn,pin,tp,n,m,mod,hd,tl,ans1,ans2;
char B[<<],*SS,*TT; inline char getc() {return SS==TT&&(TT=(SS=B)+fread(B,,<<,stdin),SS==TT)?EOF:*SS++;}
inline int read()
{
register int n=; char c;
do c=getc(); while (c<'' || c>'');
do n=n*+c-'',c=getc(); while (c>='' && c<='');
return n;
} inline void ins(int x,int y) {e[++pin]=(edge){hr[x],y}; hr[x]=pin;} void tarjan(int x)
{
register int i,lt;
low[x]=lt=++dfn;
u[x]=ink[x]=true; st[++tp]=x;
for (i=hr[x];i;i=e[i].nex)
{
if (u[e[i].to]&&!ink[e[i].to]) continue;
if (!u[e[i].to]) tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
}
if (low[x]==lt)
for (;st[tp+]!=x;--tp) ink[st[tp]]=false,bel[st[tp]]=x,++w[x];
} int main()
{
register int i,x;
n=read(); m=read(); mod=read();
for (i=;i<=m;++i) b[i].x=read(),b[i].y=read(),ins(b[i].x,b[i].y);
for (i=;i<=n;++i) if (!u[i]) tarjan(i);
memset(hr,,sizeof(hr)); pin=;
for (i=;i<=m;++i)
if (bel[b[i].x]!=bel[b[i].y])
ins(bel[b[i].x],bel[b[i].y]),++d[bel[b[i].y]];
for (i=hd=;i<=n;++i) if (bel[i]==i&&!d[i]) q[++tl]=i,f1[i]=w[i],f2[i]=;
for (;hd<=tl;++hd)
{
for (x=q[hd],i=hr[x];i;i=e[i].nex)
{
if (!--d[e[i].to]) q[++tl]=e[i].to;
if (!u[e[i].to]) continue; else u[e[i].to]=false;
if (f1[x]+w[e[i].to]>f1[e[i].to]) f1[e[i].to]=f1[x]+w[e[i].to],f2[e[i].to]=f2[x];
else if (f1[x]+w[e[i].to]==f1[e[i].to]) f2[e[i].to]+=f2[x],f2[e[i].to]-=f2[e[i].to]>=mod?mod:;
}
for (i=hr[x];i;i=e[i].nex) u[e[i].to]=true;
}
for (i=;i<=n;++i)
if (f1[i]>ans1) ans1=f1[i],ans2=f2[i];
else if (f1[i]==ans1) ans2+=f2[i],ans2-=ans2>=mod?mod:;
printf("%d\n%d",ans1,ans2);
}
Last Word
有向图用tarjan缩完点得到的是拓扑图,无向图缩环会变成树(森林)。
用了n+e光速读入后立竿见影地卡到了这道题的rank2。(代码画风崩坏不可避)
[BZOJ]1093 最大半连通子图(ZJOI2007)的更多相关文章
- bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- BZOJ 1093 最大半连通子图 题解
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2767 Solved: 1095[Submit][S ...
- BZOJ 1093 最大半连通子图
缩点求最长链. #include<iostream> #include<cstdio> #include<cstring> #include<algorith ...
- Tarjan水题系列(5):最大半连通子图 [ZJOI2007 luogu P2272]
题目 大意: 缩点后转为求最长链的长度和最长链的个数 思路: 看懂题就会做系列 长度和个数都可以拓扑排序后DP求得 毕竟是2007年的题 代码: 如下 #include <cstdio> ...
- BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)
题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ...
- BZOJ 1093 [ZJOI2007]最大半连通子图
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1986 Solved: 802[Submit][St ...
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2286 Solved: 897[Submit][St ...
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- 【刷题】BZOJ 1093 [ZJOI2007]最大半连通子图
Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到 ...
随机推荐
- css变化代码
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> ...
- 函数式编程之foldLeftViaFoldRight
问题来自 Scala 函数式编程 一书的习题, 让我很困扰, 感觉函数式编程有点神学的感觉.后面看懂之后, 又觉得函数式编程所提供的高阶抽象是多么的强大. 这个问题让我发呆了好久, 现在把自己形成的想 ...
- Mongodb中 Documents文档说明
mongodb使用BSON格式存储数据记录. 如下图: 文档结构 文档有键值对组成, 有以下结构: { field1: value1, field2: value2, ... ...
- JAVA_SE基础——7.常量&变量
上一篇,我讲了标识符&关键字 这篇我来解释下变量&常量~~~ 变量与常量这两个概念相信大家都不会感到陌生,在数学中就已经涉及了变量与常量.理解变量与常量,可以举这样一个例子: 例 ...
- Java面试题(二)
系统整理了一下有关Java的面试题,包括基础篇,javaweb篇,框架篇,数据库篇,多线程篇,并发篇,算法篇等等,陆续更新中.其他方面如前端后端等等的面试题也在整理中,都会有的. 注:文末有福利! 1 ...
- vue组件详解(二)——使用props传递数据
在 Vue 中,父子组件的关系可以总结为 props向下传递,事件向上传递.父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息.看看它们是怎么工作的. 一.基本用法 组件不仅仅 ...
- AutoCAD中的扩展字典及扩展记录(C#)
在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得.在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode.感兴趣的也可以了解一下扩展数据的相关内 ...
- jquery下关于input和label的关于点击事件的坑
待填坑: 法院费用结算页面的案件类型
- 老男孩python学习之作业一购物小程序
想学编程由来已久 始终没有个结果,痛心不已 如今再次捡起来,望不负期望,不负岁月 ......一万字的废话...... 先介绍一下我的自学课程吧 "路飞学城"的<python ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...