描述 Description
在社会经济高速发展的今天,借助高科技手段,组建太空战队的愿望就快实现了。
战队属下有N个航天员。作为空军选拔上来的佼佼者,每个航天员都有与生俱来的骄傲——他们每个人都认为自己是最强的或者是第二强的。这样,如何分组就成了司令官的难题了。司令官分组的方法是这样的:
步骤1:任意选择一个未被分组的航天员,记为当前航天员.
步骤2:把当前航天员分入一个新的组.
步骤3:如果当前航天员心目中最强的那个航天员(记为Q航天员)还没有被分组,那么把Q航天员分入当前航天员所在组,并把Q航天员作为当前航天员并重复步骤3;如果Q航天员已经被分组,那么重复步骤1,直至所有航天员都被分入了某个组。
司令官想请你帮忙计算:按上面的分组方式,最多/最少能分成几个组。
输入格式 Input Format
第一行一个整数N,表示航天员的数目。
接下来N行每行1个整数,第i+1行的整数a[i](1<=a[i]<=N)表示第i位航天员心目中最强的航天员。如果a[i]=i,则表示第i个航天员认为自己是最强的。
输出格式 Output Format
一行,用空格隔开的两个整数A,B,表示按照司令官的分组方法最多和最少能够分成多少组.
样例输入 Sample Input [ 复制数据]
4 2 3 4 2
样例输出 Sample Output [ 复制数据]
2 1
时间限制 Time Limitation
每个测试点1s
注释 Hint
组数最多的一种分组过程:
首先把2分入第一组,接下来,按照第3步的要求,3、4应该也被分入第一组。
接下来,把1分入第2组。

组数最少的一种分组过程:
首先把1分入第一组,接下来,按照第3步的要求,2、3、4也应该被分入第一组。

对于50%的数据,N<=1000.
对于100%的数据,N<=100000.

这道题看似简单,实则不然。

很容易看出来的是,最多的个数就是强连通分量的个数。即每次选择一个没有出度的强连通分量然后把它去除,必然是最大解。

证明:

假设强连通分量A无出度,强连通分量B又出度,并有一条边到A。
如果先选择A中的一个点,则B必定被访问,因此组数不会因为B而减少。

分两种情况:当A有入度,则组数不会因为B而减少。

当A无入度,则A和B被分入同一组,组数减1。

综上所述,每次选择有入度的强连通分量,答案总是小于等于每次选择没有入度的强连通分量所得的答案。

因此最大解等于强连通分量个数。

根据以上我们容易发现每次选择无入度的强连通分量,恰好是最小解!

实现方式就是缩点建图。

注意求最小解,我一开始没有严格证明,想当然地数连通分量的个数,忽略了这是有向图的问题。存在这样的反例:

如果是错误的方法,算出来是1。而正确的方法算出来应该是2。很明显左边两个点不能够分到同一组。

#include <cstdio>
#include <string>
#include <cstring>long T = 0;
long DFN[100010];
long LOW[100010];
bool Instack[100010];
long Belong[100010];
long Stack[100010];
bool vis[100010];
long cnt = 0;
bool rudu[100010];
long e[100010];
long top = 0;long getint()
{long rs=0;bool sgn=1;char tmp;do tmp=getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;
}void tarjan(long u)
{DFN[u] = LOW[u] = ++T;Instack[u] = true;Stack[++top] = u;if (!DFN[e[u]]){tarjan(e[u]);if (LOW[e[u]] < LOW[u]){LOW[u] = LOW[e[u]];}}else if (Instack[e[u]]){if (DFN[e[u]] < LOW[u]){LOW[u] = DFN[e[u]];}}if (LOW[u] == DFN[u]){long v;cnt ++;do{v = Stack[top--];Belong[v] = cnt;Instack[v] = false;}while (v != u);}
}int main()
{freopen("universe.in","r",stdin);freopen("universe.out","w",stdout);long n = getint();for (long i=1;i<n+1;i++){e[i] = getint();}for (long i=1;i<n+1;i++){if (!DFN[i]){tarjan(i);}}printf("%ld",cnt);for (long i=1;i<n+1;i++){long f = Belong[i];long t = Belong[e[i]];if (f != t){rudu[t] = true;}}long ans2 = 0;for (long i=1;i<cnt+1;i++){if (!rudu[i]){ans2 ++;}}printf(" %ld",ans2);return 0;
}

【强连通分量】太空战队相关推荐

  1. 极小连通子图和极大连通子图_强连通分量与拓扑排序

    前言 由于GacUI里面开始多处用上拓扑排序,我决定把之前瞎JB搞出来的算法换掉,换成个正式的.之前我自己弄了个写起来很简单的算法,然后每一处需要用到的地方我就重新做一遍.当然这样肯定也是不行的,我觉 ...

  2. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  3. HDU4635(强连通分量+Kosaraju算法)

    题意:给出一个有向图,最多添加多少条边使这个图依然不是强连通图:当这个图是强连通图时,输出-1: 求解思路:强连通分量求解: 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. ...

  4. poj3352(强连通分量)

    题意:添加多少边才能使这个无向图为双连通分量. 注意:双连通分量适用于无向图:而强连通分量适用于有向图.但是这两个概念都是一样的. #include<iostream> #include& ...

  5. poj2553(强连通分量)

    题意:给出有向图,图的底部是所有汇节点的子集,即,底部(G)={v∈V\x-∀w∈V:(v→w)⇒(w→v)},w在--里面G可以从v, v也可从w.让我们求有多少个点是绘点的问题. 思路:先求解出强 ...

  6. poj2186(强连通分量)

    思路:找出出度为0 的顶点,如果出度为0的顶点大于1,则解为零,否则解就是出度为零的顶点的连通分支数. 刚开始是没有理解这道题的,也是看了大神之后才理解的. 方法一: #include<iost ...

  7. poj1236(强连通分量)

    题意: (1).至少需要向多少个学校发放软件,要使这个网络中的所有学校都能得到软件 (2).至少需要添加多少条边,才能使这个网络成为一个强连通分量图. 思路:首先求解强连通分量,如果不是同一个强连通分 ...

  8. HDU5934(强连通分量)

    题意:主要在诈弹爆炸的范围内如果存在其他的诈弹,那么在周围的诈弹也将会被引爆,这样思路就可以想到强连通分量了: 思路:先求解强连通分量,在找到强连通分量时,也求解出这个强连通分量的最小费用mincos ...

  9. HDU2767(强连通分量+Kosaraju算法)

    题意:需要加多少边才能把一个图变成强连通分量 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. 强连通分量:在非强连通图的有向图中,选取部分点为强连通图,该强连通子图称为强连 ...

最新文章

  1. 瑞典皇家理工学院工程实例:Sound localization
  2. 成功解决Exception “unhandled ImportError“cannot import name ‘imresize‘ from ‘imageio‘
  3. Oracle Q-quote delimiter Quote(q) 字符串原样输出
  4. C语言 · 出栈次序
  5. centos使用git安装nvm
  6. 计算机网络与维护考试题,《网络管理与维护》试题库.doc
  7. 英伟达有魔力,Uber小心翼翼 | 跟着开复去硅谷Day1
  8. ES6基础教程一 学习笔记
  9. C#基础5:字符串操作
  10. 【层级多标签文本分类】基于预训练语言模型的BERT-CNN多层级专利分类研究
  11. 2019考研数学汤家凤张宇李永乐复习资料
  12. 安装搭配VUE使用的UI框架ElementUI
  13. js实现一键复制到剪切板上_原生js实现一键复制到剪切板的功能
  14. Chrome划词插件-有道词典
  15. SCHNOKA施努卡:锂电池密封性焊接质量视觉检测
  16. 备份一下mysql笔记
  17. FDE中的金属边界条件和PML边界条件的选取
  18. JasperReport
  19. 【STM32】HAL库 SPI DMA UART驱动开发
  20. C++之 system(“pause“); 与 getchar(); 防止控制台闪退

热门文章

  1. unity 学习笔记 受伤机制与反弹效果
  2. EWMA 指数加权移动平均 模型
  3. 铜线的载流能力问题。
  4. 受Prometheus启发的开源日志工具:Loki
  5. nas4free 安装mysql_在FreeNAS上安装MySQL和phpMyAdmin
  6. android实习日志_2016年3月11日Android实习日记
  7. 52abp框架asp.net core Angular快速开发实战视频教程
  8. 杰理之芯片型号编号说明【篇】
  9. 微信测试号实现个人第三方PC端网站二维码登录(代码实现篇)
  10. 移动端H5直播/点播前端入坑简易手册