有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1,但是如果2也欢迎3那么1也欢迎3.
给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量。
用强联通分量做
首先求出联通分量的个数,然后依次求各个联通分量的出度,如果仅有一个连通分量出度为0则这个联通分量内的点的个数就是答案; 所以在用KO算法的时候还要判短是否这个最后的连通分量都可达
 
KO算法
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<vector>
  5. using namespace std;
  6. const int MAX_V = ;
  7. int V; // 顶点数
  8. vector<int> G[MAX_V]; // 图的邻接表表示
  9. vector<int> rG[MAX_V]; // 把边反向后的图
  10. vector<int> vs; // 后序遍历顺序的顶点列表
  11. bool used[MAX_V]; // 访问标记
  12. int cmp[MAX_V]; // 所属强连通分量的拓扑序322 第 4 章 登峰造极——高级篇
  13. void add_edge(int from, int to)
  14. {
  15. G[from].push_back(to);
  16. rG[to].push_back(from);
  17. }
  18. void dfs(int v)
  19. {
  20. used[v] = true;
  21. for (int i = ; i < G[v].size(); i++)
  22. {
  23. if (!used[G[v][i]]) dfs(G[v][i]);
  24. }
  25. vs.push_back(v);
  26. }
  27. void rdfs(int v, int k)
  28. {
  29. used[v] = true;
  30. cmp[v] = k;
  31. for (int i = ; i < rG[v].size(); i++)
  32. {
  33. if (!used[rG[v][i]]) rdfs(rG[v][i], k);
  34. }
  35. }
  36. int scc()
  37. {
  38. memset(used, , sizeof(used));
  39. vs.clear();
  40. for (int v = ; v < V; v++)
  41. {
  42. if (!used[v]) dfs(v);
  43. }
  44. memset(used, , sizeof(used));
  45. int k = ;
  46. for (int i = vs.size() - ; i >= ; i--)
  47. {
  48. if (!used[vs[i]]) rdfs(vs[i], k++);
  49. }
  50. return k;
  51. }
  52.  
  53. int main( )
  54. {
  55. int n,m;
  56. scanf("%d%d",&n,&m);
  57. V=n;
  58. while(m--)
  59. {
  60. int u,v;
  61. scanf("%d%d",&u,&v);
  62. u-- ; v-- ;
  63. add_edge(u,v);
  64. }
  65. n=scc();
  66. int u=-,ans=,fa=;
  67. for(int i= ; i<V ; i++)
  68. {
  69. if(cmp[i]==n-)///最后一个拓扑序
  70. {
  71.  
  72. u=i;
  73. ans++;
  74. }
  75. }
  76. ///检查是否从所有点可达
  77. memset(used,false,sizeof(used));
  78. rdfs(u,);//在跑一遍dfs,利与之后判断可达
  79. for(int i= ; i<V ; i++)
  80. {
  81. if(!used[i])
  82. {
  83. ans=;
  84. break;
  85. }
  86. }
  87. if(fa==)
  88. printf("%d\n",ans);
  89. else
  90. puts("");
  91. }

TA算法

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <vector>
  7. #include <stack>
  8. using namespace std;
  9. #define M 1000009
  10. vector<int> edge[M];
  11. stack<int> ss;
  12. int n,m,tot,scc;
  13. int low[M],DFN[M],belong[M];
  14. int out[M],num[M];
  15. bool instack[M];
  16. void init()
  17. {
  18. for(int i = ;i < n;i++)
  19. {
  20. edge[i].clear();
  21. }
  22. tot = ;
  23. scc = ;
  24. while(!ss.empty()) ss.pop();
  25. memset(low,,sizeof(low));
  26. memset(DFN,,sizeof(DFN));
  27. memset(out,,sizeof(out));
  28. memset(belong,,sizeof(belong));
  29. }
  30. void add_edge(int u,int v)
  31. {
  32. edge[u].push_back(v);
  33. }
  34. void tarjan(int u)
  35. {
  36. instack[u] = true;
  37. low[u] = DFN[u] = ++tot;
  38. ss.push(u); //将刚访问的节点入栈
  39. for(int i = ;i < edge[u].size();i++)
  40. {
  41. int v = edge[u][i];
  42. if(!DFN[v]) //没有被访问过
  43. { // (不能写成不在栈中,因为在栈中的一定是访问过的,但是不在栈中的也可能访问过,只是已经划入之前的强连通分量了)
  44. tarjan(v);
  45. low[u] = min(low[u],low[v]);
  46. }
  47. else if(instack[v]) // 指向栈中节点的后向边
  48. {
  49. low[u] = min(low[u],DFN[v]);
  50. }
  51. }
  52. if(DFN[u] == low[u]) // u 为一个强连通分量的根
  53. {
  54. scc++;//强连通分量的编号
  55. int v;
  56. do
  57. {
  58. v = ss.top();
  59. ss.pop();
  60. belong[v] = scc; //标记每个节点所在的强连通分量
  61. num[scc]++; //每个强连通分量的节点个数
  62. }while(u != v);
  63. }
  64. }
  65. int main( )
  66. {
  67. init();
  68. scanf("%d%d",&n,&m);
  69. for(int i= ; i<m ; i++)
  70. {
  71. int u,v;
  72. scanf("%d%d",&u,&v);
  73. add_edge(u-,v-);
  74. }
  75. for(int i= ; i<n ; i++)
  76. {
  77. if(!DFN[i])
  78. tarjan(i);
  79. }
  80.  
  81. for(int i= ; i<n ; i++)
  82. {
  83. for(int j= ; j<edge[i].size() ; j++)
  84. {
  85. int v=edge[i][j];
  86. if(belong[i]!=belong[v])
  87. out[belong[i]]++;//出度
  88. }
  89. }
  90. int sum=;
  91. int ans=;
  92. for(int i= ; i<=scc ; i++)
  93. {
  94. if(!out[i])//答案在出度为0的连通分量
  95. {
  96. sum++;
  97. ans = num[i];///这个连通分量的数目
  98. }
  99. }
  100. if(sum==)///肯定只有一个,因为假设有两个的话,这两个不可能是连通的
  101. printf("%d\n",ans);
  102. else
  103. printf("0\n");
  104.  
  105. }

poj2186-Popular Cows(强连通分支)的更多相关文章

  1. 强连通分量tarjan缩点——POJ2186 Popular Cows

    这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...

  2. 洛谷——P2341 [HAOI2006]受欢迎的牛//POJ2186:Popular Cows

    P2341 [HAOI2006]受欢迎的牛/POJ2186:Popular Cows 题目背景 本题测试数据已修复. 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所 ...

  3. POJ2186 Popular Cows [强连通分量|缩点]

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31241   Accepted: 12691 De ...

  4. POJ2186 Popular Cows 【强连通分量】+【Kosaraju】+【Tarjan】+【Garbow】

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 Des ...

  5. 【Tarjan缩点】POJ2186 Popular Cows

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35644   Accepted: 14532 De ...

  6. poj2186 Popular Cows 题解——S.B.S.

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29642   Accepted: 11996 De ...

  7. POJ-2186 Popular Cows,tarjan缩点找出度为0的点。

    Popular Cows 题意:一只牛崇拜另外一只牛,这种崇拜关系可以传导.A->B,B->C =>A->C.现在给出所有的关系问你有多少牛被其他所有的牛都崇拜. 思路:就是一 ...

  8. POJ2186 Popular Cows

    Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= ...

  9. POJ2186 Popular Cows(强连通分量)

    题目问一个有向图所有点都能达到的点有几个. 先把图的强连通分量缩点,形成一个DAG,那么DAG“尾巴”(出度0的点)所表示的强连通分量就是解,因为前面的部分都能到达尾巴,但如果有多个尾巴那解就是0了, ...

  10. POJ2186 Popular Cows 强连通分量tarjan

    做这题主要是为了学习一下tarjan的强连通分量,因为包括桥,双连通分量,强连通分量很多的求法其实都可以源于tarjan的这种方法,通过一个low,pre数组求出来. 题意:给你许多的A->B ...

随机推荐

  1. Oracle 12c 多租户 CDB 与 PDB之 shared undo 与 Local undo 切换

    undo 在12C R1版本中只支持Global Shared Undo模式, 所有container共享一个UNDO表空间, 目前保留这种模式只是为了升级过渡, 在12C R2引入了PDB Loca ...

  2. [转]为什么GOF的23种设计模式里面没有MVC?

    GoF (Gang of Four,四人组, <Design Patterns: Elements of Reusable Object-Oriented Software>/<设计 ...

  3. 用遗传算法解决TSP问题

    浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html Description \(小m\)在踏上寻找\(小o\)的路程之后不小心碰到了大魔王\(fat ...

  4. CentOS6.5中的vsftpd安装配置

    安装ftp 1.使用chkconfig 来查看是否装有vsftpd服务: 2.使用yum命令直接安装:yum -y install vsftpd 3.然后为它创建日志文件:touch /var/log ...

  5. Poj_1004_FinancialManagement

    一.Description Larry graduated this year and finally has a job. He's making a lot of money, but someh ...

  6. 问题11:如何进行反向迭代 & 如何实现反向迭代

    # 有关列表问题,参考:Python:列表list 案例: 需求:实现一个连续浮点数发生器FloatRange(和range类似),根据给定范围(start,end)和步进值(step),产生一系列连 ...

  7. sql server 2008 开启1433端口,开启远程连接

    通常情况下只需要设置两处

  8. play的job执行方式

    除了使用Quartz CRON trigger, 还可以写一个action来专门触发job,这样子就可以随时启动job的开始,而且还能并行其他的任务.较方便.

  9. JOptionPane简介

    ------------------siwuxie095                                 JOptionPane 是弹出窗体(对话框)的集合类,它本身 并不是一个具体的 ...

  10. 22、IDP-ASE

    IDPASE https://github.com/bdeonovic/IDPASE.jl Prepare necessary input files (1)FASTQ file of your hy ...