题目链接:https://vjudge.net/contest/219056#problem/H

题意:先输入n,代表接下来有n个点,接下来n行,第i行里面的数(假设是)a,b...0(到0表示结束),表示点i和a,b有一条从i到a,b的有向边,现在叫我们求出两个答案,

第一个答案就是至少要选择几个点作为起点,才可以到达所有的点,

第二个答案就是至少要添加几条有向边才可以使得每次随便选择一个点都可以到达其他所有点(整个图就是一个强连通分量)。

思路:首先计算第一个答案:至少要几个点作为起点才可以到达其他所有点,如果是同一个强连通分量的点肯定可以相互到达,那我们就先缩点,得到一个有向无环图,那么我们的答案是不是就是缩点之后的图中入度为0的点,因为通过这些入度为0的点一定可以到达其他入度非0的点,那么我们的第一个答案就是缩点之后入度为0的点的个数。

第二个答案:至少要增加几条有向边才可以使这个图里面的点可以两两相互到达(只有一个强连通分量),首先在有向图里面如果没有入度为0并且也没有出度为0的点,那么这个图就是强连通的(应该不包括自己指向自己),在我们缩点之后,对于那些入度为0的点,我们想要到达,则必须要有一条有向边到达这些入度为0的点,假设入度为0的点的数量是in_um,对于出度为0,的点,我们必须至少连接一条有向边使得这个点可以到达其他点,假设出度为0的点的数量是out_num,那么第二个答案就是max(in_num,out_num),因为我们可以增加有向边从出度为0的点指向入度为0的点,答案就是更大的数。

这里有个大坑就是如果缩点之后强连通分量数目为1,那么直接输出1 0就可以了,特例,我还是百度才知道的。

代码:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. #include<map>
  6. #include<stack>
  7. #include<cmath>
  8. #include<vector>
  9. #include<set>
  10. #include<cstdio>
  11. #include<string>
  12. #include<deque>
  13. using namespace std;
  14. typedef long long LL;
  15. #define eps 1e-8
  16. #define INF 0x3f3f3f3f
  17. #define maxn 105
  18. vector<int>vec[maxn];
  19. int n,m,k,t;
  20. int vis[maxn];
  21. int dfn[maxn],low[maxn],color[maxn],s[maxn],time,ans,top;
  22. int in[maxn],out[maxn],flag[maxn][maxn];
  23. void init()
  24. {
  25. memset(vis,,sizeof(vis));
  26. memset(dfn,,sizeof(dfn));
  27. memset(in,,sizeof(in));
  28. memset(out,,sizeof(out));
  29. memset(flag,,sizeof(flag));
  30. for(int i=;i<=n;i++)
  31. {
  32. vec[i].clear();
  33. }
  34. time=top=ans=;
  35. }
  36. void DFS(int u)
  37. {
  38. dfn[u]=low[u]=++time;
  39. s[top++]=u;
  40. vis[u]=true;
  41. for(int i=;i<vec[u].size();i++)
  42. {
  43. int v=vec[u][i];
  44. if(!dfn[v])
  45. {
  46. DFS(v);
  47. low[u]=min(low[u],low[v]);
  48. }
  49. else if(vis[v])
  50. low[u]=min(low[u],dfn[v]);
  51. }
  52. if(low[u]==dfn[u])
  53. {
  54. ans++;
  55. int v;
  56. do{
  57. v=s[--top];
  58. vis[v]=false;
  59. color[v]=ans;//染色
  60. }while(u!=v);
  61. }
  62. }
  63. void tarjan()
  64. {
  65. for(int i=;i<=n;i++)
  66. {
  67. if(!dfn[i])
  68. DFS(i);
  69. }
  70. }
  71. void cal()//计算出入度
  72. {
  73. for(int i=;i<=n;i++)
  74. {
  75. for(int j=;j<vec[i].size();j++)
  76. {
  77. int a=color[i];
  78. int b=color[vec[i][j]];
  79. if(a!=b)
  80. {
  81. if(flag[a][b]==)//标记a和b之间有没有有向边
  82. {
  83. out[a]++;
  84. in[b]++;
  85. flag[a][b]++;
  86. }
  87.  
  88. }
  89. }
  90. }
  91. }
  92. int main()
  93. {
  94. while(scanf("%d",&n)!=EOF)
  95. {
  96. init();
  97. for(int i=;i<=n;i++)
  98. {
  99. int v;
  100. while(scanf("%d",&v)&&v)
  101. {
  102. vec[i].push_back(v);
  103. }
  104. }
  105. tarjan();
  106. if(ans==)//特例
  107. {
  108. printf("1\n0\n");
  109. continue;
  110. }
  111. cal();//计算出入度
  112. int in_num=,out_num=;//入度为0和出度为0的点的数目
  113. int sum1=,sum2=;
  114. for(int i=;i<=ans;i++)//注意ans,这是缩点之后点的数量,不要写成n了
  115. {
  116. if(!in[i])
  117. in_num++;
  118. if(!out[i])
  119. out_num++;
  120. }
  121. sum1=in_num;
  122. sum2=max(in_num,out_num);
  123. printf("%d\n%d\n",sum1,sum2);
  124. }
  125. return ;
  126. }

缩点+出入度 poj1236的更多相关文章

  1. poj 1236 Network of Schools(强连通、缩点、出入度)

    题意:给出一个有向图.1:问至少选出多少个点,才能沿有向边遍历所有节点.2:问至少加多少条有向边,使原图强连通. 分析:第一个问题,缩点后找所有树根(入度为0).第二个问题,分别找出入度为0和出度为0 ...

  2. Tarjan缩点求入度为零的点的个数问题

    Description: 一堆人需要联系,但如果x 可以联系 y,你联系了x就不用联系y了,你联系一个人都会有固定的花费,问你最小联系多少人,和最小花费 Solution: Tarjan缩点,求出缩点 ...

  3. POJ1236 (强连通分量缩点求入度为0和出度为0的分量个数)

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13804   Accepted: 55 ...

  4. poj 2553 The Bottom of a Graph(强连通、缩点、出入度)

    题意:给出一个有向图G,寻找所有的sink点.“sink”的定义为:{v∈V|∀w∈V:(v→w)⇒(w→v)},对于一个点v,所有能到达的所有节点w,都能够回到v,这样的点v称为sink. 分析:由 ...

  5. poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11047   Accepted: 4725 ...

  6. poj 1659 Frogs' Neighborhood(出入度、可图定理)

    题意:我们常根据无向边来计算每个节点的度,现在反过来了,已知每个节点的度,问是否可图,若可图,输出一种情况. 分析:这是一道定理题,只要知道可图定理,就是so easy了  可图定理:对每个节点的度从 ...

  7. HDU 4635 Strongly connected(强连通分量,变形)

    题意:给出一个有向图(不一定连通),问最多可添加多少条边而该图仍然没有强连通. 思路: 强连通分量必须先求出,每个强连通分量包含有几个点也需要知道,每个点只会属于1个强连通分量. 在使图不强连通的前提 ...

  8. poj1236强连通缩点

    题意:给出每个学校的list 代表该学校能链接的其他学校,问1:至少给几个学校资源使所有学校都得到:2:至少加多少个边能让所有学校相互连通: 思路:1:找出缩点后入度为零的点个数  2:找出缩点后入度 ...

  9. poj1236 Network of Schools ,有向图求强连通分量(Tarjan算法),缩点

    题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点.才干做到从这些顶点出发,能够到达所有顶点 2) 至少要加多少条边.才干使得从不论什么一个顶点出发,都能到达所有顶点   ...

随机推荐

  1. linux 开关机指令

    shutdown -h now  现在关机 shutdown -h  1  1分钟后电脑关机 su  切换 用户 halt 关机 reboot 重启 sync :保存

  2. delphi 属性编辑器

    RegisterPropertyEditor TPictureEditor = class(TClassProperty)   RegisterPropertyEditor(TypeInfo(TPic ...

  3. Installing PHP5 on Ubuntu Server

    When installing PHP 5 from source I ran into the following problems and solutions: Problem:configure ...

  4. Cmake 编译opengl开源库glfw工程及使用

    使用的是cmake gui进行编译的,路径输入好之后,点configure配置vs版本,这里是vs2013版本,然后如果画面出现红色的 需要再点击一下 Generate 然后直接点open proje ...

  5. c++复习:C++输入和输出流

    C++输入和输出流 1.I/O流的概念和流类库的结构 程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件. C++输入输出包含以下三个方面的内容: 对系统指定的标准 ...

  6. ReactiveX 学习笔记(17)使用 RxSwift + Alamofire 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...

  7. APP安全性测试总结--网上转载

    移动APP安全测试   老鹰a0人评论7103人阅读2018-08-06 16:22:07   1        移动APP安全风险分析 1.1     安全威胁分析 安全威胁从三个不同环节进行划分, ...

  8. Eclipse编译Android项目时出现的问题:Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead.

    Consle: Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead. Please use Andro ...

  9. Ajax 学习 第三篇

    1.什么是json 第一种方法 第二种方法 比较evar and jsondata 任何时候使用EVAR要特别小心,他不会管输入对象的类型 JSONLint可以在线校验代码的正确性 改写代码

  10. NYOJ201-作业题-(dp)

    201-作业题 内存限制:64MB 时间限制:3000ms 特判: No通过数:9 提交数:28 难度:3 题目描述: 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计 ...