Description

定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 从$v$到$u$。

给出一个有向图, 要求出节点最多的半联通子图,  并求出方案数。

Solution

先进行一次$Tarjan \ SCC$ 缩点, 得到一个有向无环图, 则半联通子图一定是一条单向的链。

然后就相当于求出最大的链的节点数, 以及有多少种链有这么多节点。

从每个入度为$0$ 的节点开始$DP$即可。 还需要注意同一对联通块的边需要判重。

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define rd read()
using namespace std;
typedef pair<int, int> P; const int N = 1e5 + ;
const int M = 1e6 + ; int head[N], tot;
int Head[N], Tot;
int low[N], dfn[N], cnt, col, c[N], r[N], sz[N], inq[N], num[N], vis[N], sum[N];
int st[N], tp;
int n, m, mod, ans1, ans2; struct edge {
int nxt, to, fr;
}e[M], E[M]; int read()
{
int X = , p = ; char c = getchar();
for(; c > '' || c < ''; c = getchar()) if(c == '-') p = -;
for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
return X * p;
} void add(int u, int v) {
e[++tot].to = v;
e[tot].nxt = head[u];
e[tot].fr = u;
head[u] = tot;
} void Add(int u, int v) {
E[++Tot].to = v;
E[Tot].nxt = Head[u];
Head[u] = Tot;
r[v]++;
} void tarjan(int u) {
low[u] = dfn[u] = ++cnt;
st[++tp] = u;
inq[u] = ;
for (int i = head[u]; i; i = e[i].nxt) {
int nt = e[i].to;
if (!dfn[nt]) tarjan(nt), low[u] = min(low[u], low[nt]);
else if (inq[nt]) low[u] = min(low[u], dfn[nt]);
}
if (dfn[u] == low[u]) {
col++;
for (;;) {
int now = st[tp--];
c[now] = col;
inq[now] = ;
sz[col]++;
if (now == u)
break;
}
}
} void dp(int u) {
if (num[u]) return;
num[u] = ;
sum[u] = sz[u];
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
if (vis[nt] == u)
continue;
dp(nt); vis[nt] = u;
if (sum[nt] + sz[u] > sum[u])
sum[u] = sum[nt] + sz[u], num[u] = num[nt];
else if (sum[nt] + sz[u] == sum[u])
num[u] = (num[u] + num[nt]) % mod;
}
} int main()
{
n = rd; m = rd; mod = rd;
for (int i = ; i <= m; ++i) {
int u = rd, v = rd;
add(u, v);
}
for (int i = ; i <= n; ++i)
if (!dfn[i]) tarjan(i);
for (int i = ; i <= tot; ++i) {
int u = e[i].fr, v = e[i].to;
if (c[u] == c[v])
continue;
Add(c[u], c[v]);
}
for (int i = ; i <= col; ++i)
if (!r[i]) dp(i);
for (int i = ; i <= col; ++i)
ans1 = max(ans1, sum[i]);
for (int i = ; i <= col; ++i)
if (ans1 == sum[i]) ans2 = (ans2 + num[i]) % mod;
printf("%d\n%d\n", ans1, ans2);
}

BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点的更多相关文章

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

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

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

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

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

  6. [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)

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

  7. bzoj 1093: [ZJOI2007]最大半连通子图【tarjan+拓扑排序+dp】

    先tarjan缩成DAG,然后答案就变成了最长链,dp的同时计数即可 就是题面太唬人了,没反应过来 #include<iostream> #include<cstdio> #i ...

  8. [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

    题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...

  9. bzoj 1093 [ZJOI2007]最大半连通子图——缩点+拓扑

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1093 缩点+拓扑,更新长度的时候维护方案数. 结果没想到处理缩点后的重边,这样的话方案数会算 ...

随机推荐

  1. 八皇后问题-dfs

    一.题意解析 国际象棋中的皇后,可以横向.纵向.斜向移动.如何在一个8X8的棋盘上放置8个皇后,使得任意两个皇后都不在同一条横线.竖线.斜线方向上?八皇后问题是一个古老的问题,于1848年由一位国际象 ...

  2. 关于log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).的问题

    解决办法(非长久之计,折中) 将该方法插入到main函数中,可以自行打印日志信息了 BasicConfigurator.configure(); //自动快速地使用缺省Log4j环境.原文链接:htt ...

  3. numpy中的数学

    1.dot,exp v = np.dot(arg1,arg2) #矩阵乘法 v2 = np.exp() # e的-x 次方

  4. linux系统上项目部署

    步骤:(特别注意:虚拟机安装的一般是32位的操作系统,jdk也必须使用32位的)查看虚拟机版本:sudo uname --m i686 //表示是32位 x86_64 // 表示是64位 查看是否已经 ...

  5. async.series

    [async.series] series适用于顺序执行异步且前后无关联的调用.对于顺序执行异步且前后有叛逆的调用,则需要使用waterfall. If any functions in the se ...

  6. Mysql 用户 创建与删除(基础1)

    Mysql是最流行的关系型数据库管理系统之一,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个 ...

  7. elastic search文档详解

    在elastic search中文档(document)类似于关系型数据库里的记录(record),类型(type)类似于表(table),索引(index)类似于库(database). 文档一定有 ...

  8. js setInterval参数设置

    语法  setInterval(code,interval) ①可以有第三个参数,第三个参数作为第一个参数(函数)的参数 ②第一个参数是函数,有三种形式: 1.传函数名,不用加引号,也不加括号,如 s ...

  9. 六:python 对象类型详解二:字符串(下)

    一:字符串方法: 方法就是与特定对象相关联在一起的函数.从技术的角度来讲,它们是附属于对象的属性,而这些属性不过是些可调用的函数罢了.Python 首先读取对象方法,然后调用它,传递参数.如果一个方法 ...

  10. as3.0拼图

    package com{ import flash.display.MovieClip; import flash.events.MouseEvent; import flash.geom.Point ...