思路:

建图时,分别建正向图edge和转置图T。用正向图edge来DFS,找出第一个被发现的强连通分支(如果该图存在题目要求的点,那么一定就是第一个被发现的)。然后用spfa跑转置图T,判断被发现的点是否可以到达所有点,如可以,就把该连通同的点数输出。否则输出0 。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<queue>
  6. #define Maxn 10100
  7. #define Maxm Maxn*10
  8. #define inf 0x7fffffff
  9. using namespace std;
  10. int index[Maxn],vi[Maxn],stack[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,E,Index[Maxn],Que[];
  11. struct Edge{
  12. int from,to,next;
  13. }edge[Maxm],T[Maxm];
  14. void addedge(int from,int to)
  15. {
  16. edge[e].from=from;
  17. edge[e].to=to;
  18. edge[e].next=index[from];
  19. index[from]=e++;
  20. T[E].from=to;
  21. T[E].to=from;
  22. T[E].next=Index[to];
  23. Index[to]=E++;
  24. }
  25. void init()
  26. {
  27. memset(index,-,sizeof(index));
  28. memset(Index,-,sizeof(Index));
  29. memset(dfn,,sizeof(dfn));
  30. memset(low,,sizeof(low));
  31. memset(vi,,sizeof(vi));
  32. e=lab=top=num=E=;
  33. }
  34. void Out(int u)//统计该连通分量点的个数
    {
  35. int i,j;
  36. do{
  37. i=stack[--top];
  38. num++;
  39. vi[i]=;
  40. }
  41. while(i!=u);
  42. }
  43. int dfs(int u)
  44. {
  45. dfn[u]=low[u]=++lab;
  46. stack[top++]=u;
  47. vi[u]=;
  48. int i,j,temp;
  49. for(i=index[u];i!=-;i=edge[i].next)
  50. {
  51. temp=edge[i].to;
  52. if(!dfn[temp])
  53. {
  54. if(dfs(temp))
  55. return ;
  56. low[u]=min(low[u],low[temp]);
  57. }
  58. if(vi[temp])
  59. low[u]=min(low[u],dfn[temp]);
  60. }
  61. if(low[u]==dfn[u])//一旦找到就不在寻找了,这样省了很多时间。
    {
  62. Out(u);
  63. return ;
  64. }
  65. return ;
  66. }
  67. int spfa(int u)//判断是否全图可达
  68. {
  69. memset(vi,,sizeof(vi));
  70. int i,temp;
  71. int head,tail;
  72. head=tail=;
  73. vi[u]=;
  74. Que[head++]=u;
  75. while(head!=tail)
  76. {
  77. temp=Que[tail++];
  78. vi[temp]=;
  79. for(i=Index[temp];i!=-;i=T[i].next)
  80. {
  81. if(!vi[T[i].to])
  82. {
  83. vi[T[i].to]=;
  84. Que[head++]=T[i].to;
  85. }
  86. }
  87. }
  88. for(i=;i<=n;i++)
  89. if(!vi[i])
  90. return ;
  91. return ;
  92. }
  93. int main()
  94. {
  95. int m,i,j,a,b;
  96. while(scanf("%d%d",&n,&m)!=EOF)
  97. {
  98. init();
  99. for(i=;i<=m;i++)
  100. {
  101. scanf("%d%d",&a,&b);
  102. addedge(a,b);
  103. }
  104. dfs();
  105. if(spfa(stack[top]))
  106. printf("%d\n",num);
  107. else
  108. printf("0\n");
  109. }
  110. return ;
  111. }

在给个缩点的方法,将每次找到的连通分支全部标号为一样,这样每个连通分支就成了一个点,然后只要判断出度为0 的点的个数,如果只有一个,那么输出这个连通分量的点数,如果存在多个,则输出0 。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<queue>
  6. #define Maxn 10100
  7. #define Maxm Maxn*10
  8. #define inf 0x7fffffff
  9. using namespace std;
  10. int index[Maxn],vi[Maxn],stack[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,list,ans[Maxn],degree[Maxn],be[Maxn];
  11. struct Edge{
  12. int from,to,next;
  13. }edge[Maxm];
  14. void addedge(int from,int to)
  15. {
  16. edge[e].from=from;
  17. edge[e].to=to;
  18. edge[e].next=index[from];
  19. index[from]=e++;
  20. }
  21. void init()
  22. {
  23. memset(index,-,sizeof(index));
  24. memset(degree,,sizeof(degree));
  25. memset(dfn,,sizeof(dfn));
  26. memset(low,,sizeof(low));
  27. memset(vi,,sizeof(vi));
  28. memset(ans,,sizeof(ans));
  29. memset(be,,sizeof(be));
  30. e=lab=top=num=list=;
  31. }
  32. void Out(int u)
  33. {
  34. int i,j;
  35. list++;
  36. do{
  37. i=stack[--top];
  38. be[i]=list;
  39. num++;
  40. vi[i]=;
  41. }
  42. while(i!=u);
  43. ans[list]=num;
  44. }
  45. int dfs(int u)
  46. {
  47. dfn[u]=low[u]=++lab;
  48. stack[top++]=u;
  49. vi[u]=;
  50. int i,j,temp;
  51. for(i=index[u];i!=-;i=edge[i].next)
  52. {
  53. temp=edge[i].to;
  54. if(!dfn[temp])
  55. {
  56. dfs(temp);
  57. low[u]=min(low[u],low[temp]);
  58. }
  59. if(vi[temp])
  60. low[u]=min(low[u],dfn[temp]);
  61. }
  62. if(low[u]==dfn[u])
  63. Out(u);
  64. return ;
  65. }
  66. int solve()
  67. {
  68. int i,j,temp,cc=;
  69. for(i=;i<=n;i++)
  70. if(!dfn[i])
  71. dfs(i);
  72. for(i=;i<=n;i++)
  73. {
  74. for(j=index[i];j!=-;j=edge[j].next)
  75. {
  76. temp=edge[j].to;
  77. if(be[i]!=be[temp])
  78. {
  79. degree[be[i]]=;
  80. }
  81. }
  82. }
  83. for(i=;i<=list;i++)
  84. {
  85. if(!degree[i])
  86. {
  87. cc++;
  88. temp=i;
  89. }
  90. }
  91. if(cc==)
  92. {
  93. return ans[temp];
  94. }
  95. else
  96. return ;
  97. return ;
  98. }
  99. int main()
  100. {
  101. int m,i,j,a,b;
  102. while(scanf("%d%d",&n,&m)!=EOF)
  103. {
  104. init();
  105. for(i=;i<=m;i++)
  106. {
  107. scanf("%d%d",&a,&b);
  108. addedge(a,b);
  109. }
  110. printf("%d\n",solve());
  111. }
  112. return ;
  113. }

poj 2186 强连通分支 和 spfa的更多相关文章

  1. poj 2049(二分+spfa判负环)

    poj 2049(二分+spfa判负环) 给你一堆字符串,若字符串x的后两个字符和y的前两个字符相连,那么x可向y连边.问字符串环的平均最小值是多少.1 ≤ n ≤ 100000,有多组数据. 首先根 ...

  2. poj 2186 强连通分量

    poj 2186 强连通分量 传送门 Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 33414 Acc ...

  3. 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)

    poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...

  4. POJ 3159 Candies(SPFA+栈)差分约束

    题目链接:http://poj.org/problem?id=3159 题意:给出m给 x 与y的关系.当中y的糖数不能比x的多c个.即y-x <= c  最后求fly[n]最多能比so[1] ...

  5. POJ 3259 Wormholes(SPFA)

    http://poj.org/problem?id=3259 题意 : 农夫约翰农场里发现了很多虫洞,他是个超级冒险迷,想利用虫洞回到过去,看再回来的时候能不能看到没有离开之前的自己,农场里有N块地, ...

  6. POJ 1860 Currency Exchange (SPFA松弛)

    题目链接:http://poj.org/problem?id=1860 题意是给你n种货币,下面m种交换的方式,拥有第s种货币V元.问你最后经过任意转换可不可能有升值.下面给你货币u和货币v,r1是u ...

  7. POJ 2186 Popular Cows(强连通分量缩点)

    题目链接:http://poj.org/problem?id=2186 题目意思大概是:给定N(N<=10000)个点和M(M<=50000)条有向边,求有多少个“受欢迎的点”.所谓的“受 ...

  8. poj 2186 Popular Cows (强连通分量+缩点)

    http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

  9. POj 2186 Popular Cows[连通分量]

    题目大意:给出N头牛,有M种关系u, v.代表u牛崇拜v牛.要求找出有多少头牛被所有牛崇拜着题目链接:http://poj.org/problem?id=2186解题思路:1>求出强连通分量,标 ...

随机推荐

  1. Codeforces 600B Queries about less or equal elements(二分查找)

    Description You are given two arrays of integers a and b. For each element of the second array bj yo ...

  2. C#学习笔记(十一):动态类型

    C#是一门静态类型的语言,但是在C#4.0时微软引入了动态类型的概念. dynamic 关键字dynamic用来定义动态对象,我们来看一下动态类型的一些特性. 调用不同类的相同方法 我们有两个或多个不 ...

  3. 新手一步一步OpenCV+Win7+Visual Studio 2013环境配置

    地点:湖南大学软件大楼211 时间:2013.12.19 昨天导师布置了个任务,要求是找出用相机拍出同一移动场景下的两张照片,计算机能根据其中的差异计算场景移动的距离和旋转角度.据说以前很牛逼的师兄完 ...

  4. 【PYTHON】二维码生成

    二维码是什么? 二维码从一维码扩展而来,增加另一维具有可读性的条码,用黑白矩形图形表示二进制数据,被设备扫描后获取其中包含的信息,二维码的长度.宽度均记载着数据,二维码具有定位点和容错机制,即便没有辨 ...

  5. 下载Xml文件方法

    #region 下载Xml文件方法 //定义委托 private delegate void DownLoadDelegate(string url, string filename); privat ...

  6. [c++]this指针理解

    #include <iostream> using namespace std; /** * this 指针理解 */ class A{ int i; public: void hello ...

  7. Ecshop实现注册页面手机号唯一的验证

    前天,公司总监提了一个需求,实现我公司商城注册会员用手机号登录这个功能,那么这个功能容易修改,在我的前一篇博文中已经给出处理方法了,但是这里有一个问题,就是如果实现了用手机号码来登陆,那么就需要在注册 ...

  8. 深入Mysql 导入导出

    mysql常用导出数据命令:1.mysql导出整个数据库  mysqldump -hhostname -uusername -ppassword databasename > backupfil ...

  9. 在Mac OS X 10.9上安装nginx

    1. 安装PCRE Download latest PCRE. After download go to download directory from terminal. $ cd ~/Downlo ...

  10. TC srm 673 300 div1

    TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...