Proving Equivalences

题意:输入一个有向图(强连通图就是定义在有向图上的),有n(1 ≤ n ≤ 20000)个节点和m(0 ≤ m ≤ 50000)条有向边;问添加几条边可使图变成强连通图;

强连通分量:对于分量中的任意两个节点,都存在一条有向的路径(顺序不同,表示的路径不同);说白了,就是任意两点都能形成一个环(但不是说只有一个环)

思路:使用Tarjan算法 (讲解得很好)即可容易地在得到在一个强连通分量中设置每个点所属的强连通分量的标号;即得到所谓的缩点;
之后就是合并所有连通分量,使得形成一个强连通分量。这个合并就是在连通分量中加有向边,即将所缺少的总入度和缺少的总的出度比较,取大的即可;(可浪费不能缺)

实现细节:开始认为可以在Tarjan中之中得到每个强连通分量的入度和出度;即在循环枚举v时再加一个else来看这条连通分量之间的边,设置出度,入度在标记点的连通分量标号时处理。但是里面涉及到好几种情况的点;不好分析与调试;还是在全部处理完了再遍历边来看是否为不同连通分量的连边;更清晰一些;

PS:要特判id == 1的情况,不然题给就是一个强连通分量,ans = 0,但是处理in[],out[]时会认为该连通分量需要和其他的连通分量连边,导致答案为1...

还有就是点的入度和出度都是对所属的连通分量而言的,开始输入时不需要处理;

时间复杂度为O(n+m)

  1. // 265MS 4792K
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. #define rep0(i,l,r) for(int i = (l);i < (r);i++)
  5. #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
  6. #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
  7. #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
  8. #define MS0(a) memset(a,0,sizeof(a))
  9. #define MS1(a) memset(a,-1,sizeof(a))
  10. const int MAXN = ;
  11. int head[MAXN],tot;
  12. struct edge{
  13. int to,w,Next;
  14. }e[MAXN];
  15. void ins(int a,int b,int w = )
  16. {
  17. e[++tot].Next = head[a];
  18. e[tot].to = b;
  19. e[tot].w = w;
  20. head[a] = tot;
  21. }
  22. const int N = ;
  23. int pre[N],dfs_clock,low[N];
  24. int belong[N],id;
  25. stack<int> S;
  26. bool stk[N];
  27. void Tarjan(int u)
  28. {
  29. pre[u] = low[u] = ++dfs_clock;
  30. S.push(u);
  31. stk[u] = true;
  32. int v;//点u所在连通分量的出度;
  33. for(int i = head[u];i;i = e[i].Next){
  34. v = e[i].to;
  35. if(pre[v] == ){
  36. Tarjan(v);
  37. low[u] = min(low[u],low[v]);
  38. }else if(stk[v]){
  39. low[u] = min(low[u],pre[v]);
  40. }
  41. }
  42. if(pre[u] == low[u]){//强连通分量的根节点
  43. ++id;
  44. do{
  45. v = S.top();
  46. S.pop();stk[v] = false;
  47. belong[v] = id;
  48. }while(v != u);
  49. }
  50. }
  51. int in[N],out[N];
  52. int main()
  53. {
  54. int T,kase = ;
  55. scanf("%d",&T);
  56. while(T--){
  57. MS0(head);tot = ;
  58. int n,m,a,b;
  59. scanf("%d%d",&n,&m);
  60. rep0(i,,m){
  61. scanf("%d%d",&a,&b);
  62. ins(a,b);
  63. }
  64. id = dfs_clock = ;
  65. rep1(i,,n) pre[i] = low[i] = belong[i] = ;
  66. rep1(i,,n)if(pre[i] == )
  67. Tarjan(i);
  68. rep1(i,,id)
  69. in[i] = out[i] = ;//并不是原图输入的入度与出度;而是缩点之后的强连通分量;
  70. rep1(u,,n){//在缩点完了之后再对边进行处理,看是否符合入度出度关系;
  71. for(int index = head[u];index;index = e[index].Next){
  72. int v = e[index].to;
  73. if(belong[u] != belong[v]){//***强连通分量之间的连边
  74. in[belong[v]]++,out[belong[u]]++;
  75. }
  76. }
  77. }
  78. int in_deg = ,out_deg = ;
  79. if(id == ){// ** WA了很多次。。
  80. puts("");
  81. continue;
  82. }
  83. rep1(j,,id){
  84. if(in[j] == ) in_deg++;
  85. if(out[j] == ) out_deg++;
  86. }
  87. printf("%d\n",max(in_deg,out_deg));
  88. }
  89. return ;
  90. }

hdu 2767 Proving Equivalences的更多相关文章

  1. HDU 2767 Proving Equivalences (强联通)

    pid=2767">http://acm.hdu.edu.cn/showproblem.php?pid=2767 Proving Equivalences Time Limit: 40 ...

  2. HDU 2767 Proving Equivalences(至少增加多少条边使得有向图变成强连通图)

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  3. HDU 2767 Proving Equivalences (Tarjan)

    Proving Equivalences Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other ...

  4. hdu 2767 Proving Equivalences(tarjan缩点)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2767 题意:问最少加多少边可以让所有点都相互连通. 题解:如果强连通分量就1个直接输出0,否者输出入度 ...

  5. HDU 2767 Proving Equivalences(强连通 Tarjan+缩点)

    Consider the following exercise, found in a generic linear algebra textbook. Let A be an n × n matri ...

  6. hdu 2767 Proving Equivalences 强连通缩点

    给出n个命题,m个推导,问最少添加多少条推导,能够使全部命题都能等价(两两都能互推) 既给出有向图,最少加多少边,使得原图变成强连通. 首先强连通缩点,对于新图,每一个点都至少要有一条出去的边和一条进 ...

  7. HDU 2767:Proving Equivalences(强连通)

    题意: 一个有向图,问最少加几条边,能让它强连通 方法: 1:tarjan 缩点 2:采用如下构造法: 缩点后的图找到所有头结点和尾结点,那么,可以这么构造:把所有的尾结点连一条边到头结点,就必然可以 ...

  8. hdoj 2767 Proving Equivalences【求scc&&缩点】【求最少添加多少条边使这个图成为一个scc】

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  9. HDU 2767.Proving Equivalences-强连通图(有向图)+缩点

    Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

随机推荐

  1. Apache Rewrite 服务器变量

    Apache提供给rewirte模块的环境变量大概分成5个类型. 第一部分: HTTP headers 部分参数 参数名称: HTTP_USER_AGENT 样例参考值: Mozilla/5.0 (W ...

  2. Forwarding a Range of Ports in VirtualBox

    STAN SCHWERTLY MAY 9, 2012 ARTICLES 3 COMMENTS Doesn't allow forwarding a range of ports through the ...

  3. oracle 不转义 &

    在为表加注释,遇到有些注释包含'&' 但又不想写eacape, 在sqlplus下,set define off   即可将&输入到数据库中.

  4. Floyd判圈算法(判断是否有环)

    介意转吗博主~~http://blog.csdn.net/thestoryofsnow/article/details/6822576,我知道不介意啦~ 问题:如何检测一个链表是否有环,如果有,那么如 ...

  5. CountDownLatch(闭锁)

    一.闭锁(Latch)    闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都 ...

  6. GitHub这么火,程序员你不学学吗? 超简单入门教程 干货

    本GitHub教程旨在能够帮助大家快速入门学习使用GitHub. 本文章由做全栈攻城狮-写代码也要读书,爱全栈,更爱生活.原创.如有转载,请注明出处. GitHub是什么? GitHub首先是个分布式 ...

  7. XML前言

    一.前言 1.XML全称"eXtensible Markup Language"(可扩展的标记语言) 2.DTD全称"Document Type Defintion&qu ...

  8. webstorm卡、闪退以及win10中jdk配置

    今天 webstorm 突然一直处于 indexing 索引状态,然后就卡死,重装也无法解决. 搜了一下后,有人说使用 64 位客户端打开就ok. 尝试打开 64 位的客户端,但是报错,没有64位 j ...

  9. ASP实现随机提取数据库记录例

    <% "一个从数据库中随机读取纪录的例子 Set Rs1=server.CreateObject ("adodb.recordset") Set Rs=server ...

  10. Android Studio如何显示行号

    Android Studio默认没有显示行号,很多同学在使用中很不习惯.本经验介绍怎样让Android Studio显示行号. 首先我们打开我们下载安装好的Android Studio 然后右击工具按 ...