poj.org/problem?id=1236

【题意】

  • 给定一个有向图,求:
  • (1)至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点
  • (2)至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点

【思路】

  • (1)强连通分量缩点后形成一个有向无环图,只要选择入度为0的顶点,其他顶点都可以被到达
  • (2)等价于一个有向无环图加最少加多少条边能够变成一个强连通图,取出度为0的点的个数和入度为0的点的个数的max,因为出度为0的点要加一条出边,入度为0的点要加一条入边
  • (2)特判特殊情况:强连通分量只有一个,这时虽然入度为0和出度为0的点都是一个,但不需要加边

【AC】

  1. //#include<bits/stdc++.h>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<string>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<cmath>
  8. using namespace std;
  9. typedef long long ll;
  10. int n;
  11. const int maxm=;
  12. const int maxn=1e2+;
  13. struct edge
  14. {
  15. int to;
  16. int nxt;
  17. }e[maxm];
  18. int head[maxn],tot;
  19. int dfn[maxn],low[maxn],id;
  20. int S[maxn],top;
  21. int num,belong[maxn];
  22. bool vis[maxn];
  23. bool in[maxn];
  24. bool out[maxn];
  25. void init()
  26. {
  27. memset(head,-,sizeof(head));
  28. tot=;
  29. id=;
  30. top=;
  31. num=;
  32. memset(dfn,,sizeof(dfn));
  33. memset(low,,sizeof(low));
  34. memset(S,,sizeof(S));
  35. memset(vis,false,sizeof(vis));
  36. memset(belong,,sizeof(belong));
  37. memset(in,false,sizeof(in));
  38. memset(out,false,sizeof(out));
  39. }
  40. void addedge(int u,int v)
  41. {
  42. e[tot].to=v;
  43. e[tot].nxt=head[u];
  44. head[u]=tot++;
  45. }
  46. void tarjan(int u)
  47. {
  48. dfn[u]=low[u]=++id;
  49. S[++top]=u;
  50. vis[u]=true;
  51. for(int i=head[u];i!=-;i=e[i].nxt)
  52. {
  53. int v=e[i].to;
  54. if(!dfn[v])
  55. {
  56. tarjan(v);
  57. low[u]=min(low[u],low[v]);
  58. }
  59. else if(vis[v]) low[u]=min(low[u],dfn[v]);
  60. }
  61. if(dfn[u]==low[u])
  62. {
  63. num++;
  64. while()
  65. {
  66. belong[S[top]]=num;
  67. vis[S[top]]=false;
  68. if(S[top--]==u) break;
  69. }
  70. }
  71.  
  72. }
  73.  
  74. int main()
  75. {
  76. while(~scanf("%d",&n))
  77. {
  78. init();
  79. for(int i=;i<=n;i++)
  80. {
  81. int x;
  82. while()
  83. {
  84. scanf("%d",&x);
  85. if(x==) break;
  86. addedge(i,x);
  87. }
  88. }
  89. for(int i=;i<=n;i++)
  90. {
  91. if(!dfn[i]) tarjan(i);
  92. }
  93. for(int u=;u<=n;u++)
  94. {
  95. for(int i=head[u];i!=-;i=e[i].nxt)
  96. {
  97. int v=e[i].to;
  98. if(belong[u]==belong[v]) continue;
  99. in[belong[v]]=true;
  100. out[belong[u]]=true;
  101. }
  102. }
  103. int ans1=;
  104. int ans2=;
  105. for(int i=;i<=num;i++)
  106. {
  107. if(!in[i]) ans1++;
  108. if(!out[i]) ans2++;
  109. }
  110. int ans=max(ans1,ans2);
  111. if(num==) ans=;
  112. printf("%d\n%d\n",ans1,ans);
  113. }
  114. return ;
  115. }

【大佬博客】

www.cnblogs.com/kuangbin/archive/2011/08/07/2130277.html

解题思路:

—        1. 求出所有强连通分量

—        2. 每个强连通分量缩成一点,则形成一个有向无环图DAG

—        3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少

在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少

加边的方法:

要为每个入度为0的点添加入边,为每个出度为0的点添加出边

假定有 n 个入度为0的点,m个出度为0的点,如何加边?

把所有入度为0的点编号 0,1,2,3,4 ....N -1

每次为一个编号为i的入度0点可达的出度0点,添加一条出边,连到编号为(i+1)%N 的那个出度0点,

这需要加n条边

若 m <= n,则

加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边

若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。

所以,max(m,n)就是第二个问题的解

此外:当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0

【强连通分量缩点】poj 1236 Network of Schools的更多相关文章

  1. POJ 1236 Network of Schools(强连通 Tarjan+缩点)

    POJ 1236 Network of Schools(强连通 Tarjan+缩点) ACM 题目地址:POJ 1236 题意:  给定一张有向图,问最少选择几个点能遍历全图,以及最少加入�几条边使得 ...

  2. POJ 1236 Network of Schools(强连通分量)

    POJ 1236 Network of Schools 题目链接 题意:题意本质上就是,给定一个有向图,问两个问题 1.从哪几个顶点出发,能走全全部点 2.最少连几条边,使得图强连通 思路: #inc ...

  3. Poj 1236 Network of Schools (Tarjan)

    题目链接: Poj 1236 Network of Schools 题目描述: 有n个学校,学校之间有一些单向的用来发射无线电的线路,当一个学校得到网络可以通过线路向其他学校传输网络,1:至少分配几个 ...

  4. poj 1236 Network of Schools(又是强连通分量+缩点)

    http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  5. POJ 1236 Network Of Schools (强连通分量缩点求出度为0的和入度为0的分量个数)

    Network of Schools A number of schools are connected to a computer network. Agreements have been dev ...

  6. POJ 1236——Network of Schools——————【加边形成强连通图】

    Network of Schools Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u ...

  7. poj 1236 Network of Schools(连通图入度,出度为0)

    http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  8. [tarjan] poj 1236 Network of Schools

    主题链接: http://poj.org/problem?id=1236 Network of Schools Time Limit: 1000MS   Memory Limit: 10000K To ...

  9. POJ 1236 Network of Schools(tarjan)题解

    题意:一个有向图.第一问:最少给几个点信息能让所有点都收到信息.第二问:最少加几个边能实现在任意点放信息就能传遍所有点 思路:把所有强连通分量缩成一点,然后判断各个点的入度和出度 tarjan算法:问 ...

随机推荐

  1. php关于精准计算的模块 BCMath

    Php: BCMath bc是Binary Calculator的缩写.bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_ope ...

  2. 并查集+思维——The Door Problem

    一.问题描述(题目链接) 有n个门和m个开关,每个开关可以控制任意多的门,每个门严格的只有两个开关控制,问能否通过操作某些开关使得所有门都打开.(给出门的初始状态). 二.问题分析 大部分开关问题首先 ...

  3. win10搭建Java环境

    一.下载地址    jdk和jre官方网址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 根据你的系统选择你需要 ...

  4. hrbust-1545-基础数据结构——顺序表(2)

    http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1545 基础数据结构——顺序表(2) ...

  5. [Tkinter 教程] 布局管理 (Pack Place Grid)

    原系列地址: Python Tkinter 简介: 本文讲述如何使用 tkinter 的布局管理 (被称作 layout managers 或 geometry managers). tkinter ...

  6. shell脚本,判断给出的字符串是否相等。

    第一种方法[root@localhost wyb]# .sh #!/bin/bash #判断给出的字符串是否相等 read -p "Please Input a number:" ...

  7. mysql:破解MySQL密码的一种方法

    1, 修改mysql配置文件/etc/my.cnf 12 [mysqld]skip_grant_tables 2, 重启mysql后直接用root用户登录(不用输入密码) 1 $ mysql -uro ...

  8. laravel 设计思想简单了解

    服务容器 laravel框架中 服务容器是整个系统功能调度配置的核心,在系统运行过程中动态的为系统提供需要的服务 从而实现了解耦 控制反转(IOC) 控制反转是一种设计模式 主要解决了系统组件之间的相 ...

  9. 力扣题目汇总(反转字符串中的单词,EXCEL表列序号,旋置矩阵)

    反转字符串中的单词 III 1.题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. 示例 1: 输入: "Let's take LeetCode ...

  10. python安装numpy模块

    1.打开网址https://pypi.python.org/pypi/numpy,找到安装的python版本对应的numpy版本. 我的python版本是 下载的对应numpy版本是 2.将numpy ...