bzoj1051[kosaraju算法]求强连通分量

之前一直用的是tarjan第一次学习到这个来试一下。

唔,就是裸的算法,然后如果出度为0的点只有一个,输出这个点的大小。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#define mm 200004
#define mn 10020
using namespace std;
stack<int>s;
queue<int>q;
struct ding{
  int to,next,sum;
}edge[mm],edge2[mm];
struct ding2{
  int xx,yy;
}a[mm];
int vis[mn],now[mn],ans,head[mn],head2[mn],node[mn],size[mn],num;
int ru[mn],n,m,vv;
bool cmp(ding2 k1,ding2 k2)
{return (node[k1.xx]==node[k2.xx]?node[k1.yy]<node[k2.yy]:node[k1.xx]<node[k2.xx]);}
void dfs(int x)
{
  if (vis[x]) return;
  vis[x]=true;
  for (int i=head[x];i;i=edge[i].next) dfs(edge[i].to);
  s.push(x);
}
void redfs(int x)
{
  if (node[x]) return;
  node[x]=num; size[num]++;
  for (int i=head2[x];i;i=edge2[i].next)
  redfs(edge2[i].to);
}
void add(int u,int v,ding*g,int*f)
{
  int p=++g[0].sum;
  g[p].to=v; g[p].next=f[u];f[u]=p;
}
int main()
{
  //freopen("cow4.in","r",stdin);
  //freopen("cow4.out","w",stdout);
  scanf("%d%d",&n,&m);
  for (int i=1;i<=m;i++)
  {
      scanf("%d%d",&a[i].xx,&a[i].yy);
      add(a[i].xx,a[i].yy,edge,head);add(a[i].yy,a[i].xx,edge2,head2);
  }
  for (int i=1;i<=n;i++) if (!vis[i])dfs(i);
  while (!s.empty())
  {
      if (!node[s.top()]) {num++; redfs(s.top());}
      s.pop();
  }
  for (int i=1;i<=m;i++) if (node[a[i].xx]>node[a[i].yy])
  {
      int t=a[i].xx;
      a[i].xx=a[i].yy;
      a[i].yy=t;
  }
  sort(a+1,a+1+m,cmp);
  int t1=0,t2=0;
  for (int i=1;i<=m;i++)
   {
      if ((node[a[i].xx]==t1)&&(node[a[i].yy]==t2)
      ||(node[a[i].xx]==node[a[i].yy])) continue;
    t1=node[a[i].xx];t2=node[a[i].yy];
    ru[t1]++;
   }
  for (int i=1;i<=num;i++)
  if (ru[i]==0) ans=size[i],vv++;
  if (vv==1) printf("%d\n",ans);
  else printf("0\n");
  return 0;
}
时间: 2024-10-09 19:01:12

bzoj1051[kosaraju算法]求强连通分量的相关文章

图论算法(6)(更新版) --- Tarjan算法求强连通分量

之前Tarjan算法求强连通分量博文中,代码实现用到了固定大小数组,扩展起来似乎并不是很方便,在java里这样来实现本身就是不太妥当的,所以下面给出一个更新版本的代码实现: package test; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util

转 tarjan算法求强连通分量

无意中想起图的强连通分量来,之前也一直想写所以今天决定来填这个坑.PS:由于本人比较懒,之前做过一个讲解的PPT,不过那是好遥远之前,年代已久早已失传,所以本文里的图来自网络.以后周末都用来填坑也挺好. ------------------------------分割线----------------------------------------- 在有向图G中,如果两个顶点间至少存在一条路径,那么这两个顶点就是强连通(strongly connected). 如果有向图G的每两个顶点都强连通

Tarjan 算法求 LCA / Tarjan 算法求强连通分量

[时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarjan算法_LCA - A_Bo的博客 - CSDN博客 Tarjan离线算法求最近公共祖先(LCA) - 初学者 - CSDN博客 最近公共祖先(LCA) - riteme.site Fuzhou University OnlineJudge P3379 [模板]最近公共祖先(LCA) - 洛谷 |

HDU 1269 迷宫城堡 tarjan算法求强连通分量

基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等,那这个点就在一个强连通分量里面,此时从栈中向外取出元素,知道取出的元素与这个点的值相等时结束,我们所有取出的点与这个点在同一个强连通分量里.下面是代码,其实代码里本来不需要id数组记录点属于哪个强连通分量的,因为题目没有做要求,但是为了保留模板完整还是带着了,以供以后复习使用. #include<c

图论算法(6) --- Tarjan算法求强连通分量

注:此算法以有向图作为输入,并按照所在的强连通分量给出其顶点集的一个划分.graph中的每个节点只在一个强连通分量里出现,即使是单点. 任选一点开始进行深度优先搜索(若dfs结束后仍有未访问的节点,则再从中任选一点再从进行).搜索过程中已访问的节点不再访问.搜索树的若干子树构成了图的强连通分量. 节点按照被访问的顺序存入栈中.从搜索树的子树返回至一个节点时,检查该节点是否是某一连通分量的根节点,并将其从栈中删除.如果某节点是强连通分量的根,则在它之前出栈且还不属于其他强连通分量的节点构成了该节点

Tarjan算法求强连通分量

一.操作过程:tarjan算法的基础是DFS.我们准备两个数组Low和Dfn.Low数组是一个标记数组,记录该点所在的强连通子图所在搜索子树的根节点的 Dfn值(很绕嘴,往下看你就会明白),Dfn数组记录搜索到该点的时间,也就是第几个搜索这个点的.根据以下几条规则,经过搜索遍历该图(无需回溯)和 对栈的操作,我们就可以得到该有向图的强连通分量. 1.数组的初始化:当首次搜索到点p时,Dfn与Low数组的值都为到该点的时间. 2.堆栈:每搜索到一个点,将它压入栈顶. 3.当点p有与点p’相连时,如

【算法】Tarjan算法求强连通分量

概念: 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通. 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图. 一个有向图中的最大强连通子图,称为强连通分量. tarjan的主要思想: 从一个点开始DFS,记录两个数组,dfn[]和low[]. 其中,dfn[i]指的是到达第i个点的时间. low[i]指第i个点直接或间接可到达的点中的最小dfn[j]. low[i]数组的初始值为dfn[i]. 举个例子,如图所示: 假如我们从第一个点开始

poj1236 Network of Schools ,求强连通分量(Tarjan算法),缩点

题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点 2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点 顶点数<= 100 求完强连通分量后,缩点,计算每个点的入度,出度. 第一问的答案就是入度为零的点的个数, 第二问就是max(n,m) // 入度为零的个数为n, 出度为零的个数为m. //kuangbin巨巨分析很棒! #include<cstdio> #include<cstring>

Tarjan算法分解强连通分量(附详细参考文章)

Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时间戳用DFN数组存储,最早祖先用low数组来存,每次dfs遍历到一个节点u,即让这两个记号等于当前时刻,在后面回溯或者判断的过程中在来更新low,DNF是一定的,因为第一次访问时刻一定.然后遍历u的子节点,也就是跟u相连的点v,依次看子节点的时间戳有没有打上,也就是看他有没有被访问过.\(1\).没