原文链接

问题描述

对于一有向图,若需要保证任选一点即可走到其它所有点,询问最少需要加多少条有向边

结论

对于一有向图,若其对应DAG中入度为0的点数为ppp,出度为0的点数为qqq,则答案数为max(p,q)max(p, q)max(p,q)

证明:
p≤qp \leq qp≤q 和 p≥qp \geq qp≥q的证明过程类似,这里仅说明p≤qp \leq qp≤q的证明过程

  1. 当p==1p == 1p==1,即1个起点,2个及以上终点时。可知起点就是一个链式关系中最前面的节点,从起点可到达链式关系中的任一点,因此从每一个终点向起点连接一条边即可实现强连通,答案为qqq
  2. 当p>1p > 1p>1时,q≥p>1q \geq p > 1q≥p>1,即2个及以上起点,2个及以上终点,且满足终点数>=起点数终点数>=起点数终点数>=起点数
    此时需要考虑一种特殊情况,p==q==2p == q == 2p==q==2。设两个起点分别为p1,p2p_1, p_2p1​,p2​,两个终点分别为q1,q2q_1, q_2q1​,q2​,则一定存在一种方案使得p1p_1p1​可以走到q1q_1q1​, p2p_2p2​可以走到q2q_2q2​,证明采用反证法,假设q2q_2q2​无法从p1p_1p1​和p2p_2p2​走到,但由于此图是一DAG,对于q2q_2q2​,不停找其前驱节点最终一定可以找到某个节点是走向q2q_2q2​的,且该节点入度为000,即是一个起点,这与所有起点都无法到达q2q_2q2​的假设相矛盾
    如果添加一条q1−>q2q_1 -> q_2q1​−>q2​的边,则问题转化为p==1p == 1p==1的情况,还需要添加111条边,故答案为222

    综上所述, 一种可行的操作方法为将p>1p > 1p>1的情况转化为p==1p == 1p==1,具体方法为将(p−1)(p - 1)(p−1)个终点连向起点,这一步需要添加(p−1)(p - 1)(p−1)条边
    此时起点数为111,终点数为q−(p−1)q - (p - 1)q−(p−1), 还需要添加q−(p−1)q - (p - 1)q−(p−1)条边
    综上,答案数为q−(p−1)+(p−1)=q=max(p,q)q - (p - 1) + (p - 1) = q = max(p, q)q−(p−1)+(p−1)=q=max(p,q)

解决思路

由上述结论可知,我们仅需将原图转变为DAG,分别统计入度为000和出度为000的点数即可
有向图转DAG可采用Tarjan实现

例题解析

题目描述

解题思路
第1问:
假如当前图为有向无环图,那么只需要计算入度为0的点的个数即可
因为对于入度非0的点,我们只需要将软件提供给它的前驱即可,对于它的前驱同理,依次类推,我们仅需要提供给该链式关系中的第一个节点即可,而链式关系中的第一个节点即为入度为0的点,故需要统计的就是入度为0的点的个数

第2问:
对题目描述进行抽象可得目标为计算“有向图转变为强连通图所需的最少加边数”,即为max(入度为0点数,出度为0点数)max(入度为0点数,出度为0点数)max(入度为0点数,出度为0点数)
将有向图转为强连通图,并分别统计入度和出度分别为0的个数即可

代码实现

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>using namespace std;const int N = 110, M = 5000;int n, m;
int h[N], e[M], ne[M], idx;
stack<int> stk;
int timestamp;
bool in_stk[N];
// tarjan维护值
int dfn[N], low[N];
int id[N], Size[N], scc_cnt;
// 统计入度出度
int din[N], dout[N];void add(int a, int b)
{e[idx] = b;ne[idx] = h[a];h[a] = idx ++;
}
void tarjan(int u)
{dfn[u] = low[u] = ++ timestamp;stk.push(u), in_stk[u] = true;for (int i = h[u]; ~i; i = ne[i]){int j = e[i];if (!dfn[j]){tarjan(j);low[u] = min(low[u], low[j]);}else if (in_stk[j]) low[u] = min(low[u], dfn[j]);}if (dfn[u] == low[u]){++ scc_cnt;int y;do {y = stk.top(); stk.pop();in_stk[y] = false;id[y] = scc_cnt;++ Size[scc_cnt];}while (y != u);}
}
int main()
{memset(h, -1, sizeof h);cin >> n;for (int i = 1; i <= n; ++ i){int y;while (cin >> y, y) add(i, y);}for (int i = 1; i <= n; ++ i)if (!dfn[i])tarjan(i);// 统计入度为0的点数p,出度为0的点数qint p = 0, q = 0;for (int i = 1; i <= n; ++ i)for (int j = h[i]; ~j; j = ne[j]){int t = e[j];int a = id[i], b = id[t];if (a != b){++ dout[a];++ din[b];}}for (int i = 1; i <= scc_cnt; ++ i){if (!din[i]) ++ p;if (!dout[i]) ++ q;}cout << p << endl;if (scc_cnt == 1) cout << 0 << endl; // 仅有一个scc,不需要连边,如果按照max(p, q)输出是错误的,需要特判else cout << max(p, q) << endl;return 0;
}

有向图转强连通图最少加边数相关推荐

  1. MP4 格式:最少加载多少数据就能渲染出视频首帧?优化短视频播放体验必须先了解它丨音视频基础

    (本文基本逻辑:MP4 封装格式概览 → 重要 Box 具体信息介绍 → 实战中对 MP4 Box 信息的使用) MP4 也称为 MPEG-4 第 14 部分,是继承 MPEG-4 第 12 部分的 ...

  2. 数仓(十)从0到1简单搭建加载数仓DWS层

    数仓(一)简介数仓,OLTP和OLAP 数仓(二)关系建模和维度建模 数仓(三)简析阿里.美团.网易.恒丰银行.马蜂窝5家数仓分层架构 数仓(四)数据仓库分层 数仓 (五) 元数据管理系统解析 数仓( ...

  3. 【算法】【华为】2019华为笔试 找终点:给定一个正整数数组,最大为100个成员,从第一个成员开始,走到数组最后一个成员最少的步骤数,

    ■题目描述 给定一个正整数数组,最大为100个成员,从第一个成员开始,走到数组最后一个成员最少的步骤数, 第一步必须从第一元素开始,1<=步长<len/2, 第二步开始以所在成员的数字走相 ...

  4. MySQL日期当前时间加月数

    MySQL日期当前时间加月数 SQL 日期: 当我们处理日期时,最难的任务恐怕是确保所插入的日期的格式,与数据库中日期列的格式相匹配. 只要数据包含的只是日期部分,运行查询就不会出问题.但是,如果涉及 ...

  5. 弘辽科技:淘宝收藏加购数指的是什么?有什么用?

    判断一个宝贝运营的效果主要是通过各方面的数据去了解的,最常见的数据就是宝贝的销量.点击率.转化率.收藏加购等等,有一些新手运营,刚开始接触电商运营,不清楚这个淘宝收藏加购数指的是什么?想要深入了解的朋 ...

  6. 增加最少的边使有向图变为强连通图

    http://codeforces.com/contest/22/problem/E 此题是这个问题的简化版本,每个点出度至多为一.先强连通缩点,每个点出度至多为一可以保证从任一个入度为0的点出发只能 ...

  7. loj 1210 (求最少的加边数使得图变成强连通)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1210 思路:首先是缩点染色,然后重建并且统计新图中的每个点的入度和出度,于是答案就是m ...

  8. HDU 4635 Strongly connected(缩点、最多可加边数使得仍然非强连通)

    整理的算法模板合集: ACM模板 HDU 4635 Strongly connected Give a simple directed graph with N nodes and M edges. ...

  9. 蓝桥杯刷题015——最少刷题数(二分法+前缀和)

    问题描述 小蓝老师教的编程课有 N 名学生, 编号依次是 1-N .第 i 号学生这学期刷题的数量是 Ai​ . 对于每一名学生, 请你计算他至少还要再刷多少道题, 才能使得全班刷题比他多的学生数不超 ...

最新文章

  1. 亚马逊专家揭秘:如何建立自动检测乳腺癌的深度学习模型
  2. linux 控制网卡流量,如何管理和控制多网卡 Linux 虚拟机的流量走向
  3. google bigtable论文原文_CTR论文笔记[1]:Wideamp;Deep
  4. HTTP深入浅出个人总结
  5. AtCoder Beginner Contest 179 总结
  6. 简单的文件上传功能实现(java)
  7. 好婚姻必定是灵魂佳偶
  8. mysql qcow2_qcow2文件格式分析
  9. 谷歌TPU2代有望取代英伟达GPU?测评结果显示…
  10. linux下检查是否安装过某软件包
  11. LVS详解(七)——LVS TUN模式实战
  12. 【ActiveMQ】消息生产者自动注入报错:Could not autowire. No beans of #39;JmsMessagingTemplate#39; type found...
  13. LoadRunner教程(18)-LoadRunner 图表合并
  14. (快)开学了,各大编程语言在群里吵翻了天!
  15. NVIDIA Jetson Xavier NX部署VINS-fusion-GPU
  16. 产品经理常用的方法论有哪些
  17. C语言三个点“...“符号含义之数组批量赋相同值
  18. glibc 2.17升级2.28,gcc 4.8.5升级9.2.0,GNU Make 3.82 升级到4.2.1,安装bison
  19. php ldap 登陆验证,LDAP用户验证功能简介
  20. 【谁年轻时没YY过】财务自由后的某一天

热门文章

  1. 51单片机和32单片机有什么区别?该从哪个开始入门学习?
  2. UAP平台常见数据有效性数据校验
  3. html flag属性,html5 的flag是什么意思?
  4. 事实表与维度表的区别与关系
  5. 细说Java垃圾回收
  6. 数据结构实验6_压缩矩阵的转置、普通转置、快速转置算法
  7. GPU-CUDA-图形渲染分析
  8. javac ‘javac‘ 不是内部或外部命令,也不是可运行的程序 的解决办法
  9. K_A11_002 基于STM32等单片机驱动DS18B20串口与OLED0.96双显示
  10. AppleCare 扫盲帖,三年苹果狗告诉你 AppleCare 到底值不值得买?