kosaraju算法应用(一)

题目链接:POJ 2186

解题思路:

kosaraju算法,本以为要缩点,但是题目只要求找到拓扑排序的一个唯一的头,可以水过——通过计算强连通分量的出度。

代码:

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n,m,v[10005],num[10005],cnt,scc,out[10005],ans[10005];
vector<int> vec[10005];
vector<int> nvec[10005];

void dfs(int index)
{
    v[index]=1;
    int len=vec[index].size();
    for(int i=0;i<len;i++)
        if(!v[vec[index][i]])
            dfs(vec[index][i]);
    num[++cnt]=index;
}

void ndfs(int index)
{
    v[index]=scc,ans[scc]++;
    int len=nvec[index].size();
    for(int i=0;i<len;i++)
        if(!v[nvec[index][i]])
            ndfs(nvec[index][i]);
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(ans,0,sizeof(ans));
        memset(vec,0,sizeof(vec));
        memset(nvec,0,sizeof(nvec));

        int x,y;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d",&x,&y);
            vec[x].push_back(y);
            nvec[y].push_back(x);
        }

        memset(v,0,sizeof(v));
        for (int i=1;i<=n;i++)
            if(!v[i])
                dfs(i);
        memset(v,0,sizeof(v));
        for(int i=cnt;i>=1;i--)
        {
            if(!v[num[i]])
            {
                scc++;
                ndfs(num[i]);
            }
        }

        memset(out,0,sizeof(out));
        int res=0,count=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<vec[i].size();j++)
            {
                if(v[i]!=v[vec[i][j]])
                    out[v[i]]++;
            }
        }
        for(int i=1;i<=scc;i++)
        {
            if(!out[i]) count++,res=ans[i];
            if(count>1) res=0;
        }

        printf("%d\n",res);
    }

    return 0;
}

下次讲缩点~

时间: 2024-10-03 14:55:46

kosaraju算法应用(一)的相关文章

Kosaraju算法解析: 求解图的强连通分量

1. 定义 连通分量:在无向图中,即为连通子图. 上图中,总共有四个连通分量.顶点A.B.C.D构成了一个连通分量,顶点E构成了一个连通分量,顶点F,G和H,I分别构成了两个连通分量. 强连通分量:有向图中,尽可能多的若干顶点组成的子图中,这些顶点都是相互可到达的,则这些顶点成为一个强连通分量. 上图中有三个强连通分量,分别是a.b.e以及f.g和c.d.h. 2. 连通分量的求解方法 对于一个无向图的连通分量,从连通分量的任意一个顶点开始,进行一次DFS,一定能遍历这个连通分量的所有顶点.所以

Kosaraju 算法检测有向图的强连通性

给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strongly Connected).如下图中,任意两个顶点都是互相可达的. 对于无向图,判断图是否是强连通的,可以直接使用深度优先搜索(DFS)或广度优先搜索(BFS),从任意一个顶点出发,如果遍历的结果包含所有的顶点,则说明图是强连通的. 而对于有向图,则不能使用 DFS 或 BFS 进行直接遍历来判断.如下图中,

Kosaraju算法详解

Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记.它的算法描述较为简单: (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序.以下图为例:     如果以1为起点遍历,访问结点的顺序如下: 结点第二次被访问即为退出之时,那么我们可以得到结点的退出顺序: (2)倒转每一条边的方向,构造出一个反图G’.然后按照退出顺序的逆序对反图进行第二次DFS遍历.我们按1.4.2.3.5的逆序第二次DFS遍历: 访问过程如下: 每次遍历得到的那

Kosaraju 算法

Kosaraju 算法 一.算法简介 在计算科学中,Kosaraju的算法(又称为–Sharir Kosaraju算法)是一个线性时间(linear time)算法找到的有向图的强连通分量.它利用了一个事实,逆图(与各边方向相同的图形反转, transpose graph)有相同的强连通分量的原始图. 有关强连通分量的介绍在之前Tarjan 算法中:Tarjan Algorithm 逆图(Tranpose Graph ): 我们对逆图定义如下: GT=(V, ET),ET={(u, v):(v,

codevs1506传话(kosaraju算法)

- - - - - - - - 一个()打成[] 看了一晚上..... /* 求强连通分量 kosaraju算法 边表存图 正反构造两个图 跑两边 分别记下入栈顺序 和每个强连通分量的具体信息 */ #include<iostream> #include<cstring> #include<cstdio> #include<stack> #define maxn 1010 #define maxx 10010 using namespace std; int

Kosaraju 算法查找强连通分支

有向图 G = (V, E) 的一个强连通分支(SCC:Strongly Connected Components)是一个最大的顶点集合 C,C 是 V 的子集,对于 C 中的每一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的. 实际上,强连通分支 SCC 将有向图分割为多个内部强连通的子图.如下图中,整个图不是强连通的,但可以被分割成 3 个强连通分支. 通过 Kosaraju 算法,可以在 O(V+E) 运行时间内找到所有的强连通分支.Ko

CSU 1612: Destroy Tunnels 强连通分量 Kosaraju算法

链接 :  http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1612 题意: 给一个矩阵A 大小N*N, B = A^1 + A^2 + A^3 + .... A^n , B中是否存在非0项. 题目可以转化为 N个点 编号为1-n, 对于任意点v,经过一些任意的步长到达u (u为所有点集的任意一个).离散数学里有图的矩阵相关知识 A^k代表了矩阵中从i到j的步长为k的方法数. 题目就是求整个图是否强连通. 学习了 Kosaraju算法 可以轻

强联通分量之kosaraju算法

首先定义:强联通分量是有向图G=(V, E)的最大结点集合,满足该集合中的任意一对结点v和u,路径vu和uv同时存在. kosaraju算法用来寻找强联通分量.对于图G,它首先随便找个结点dfs,求出每个节点最后一次访问的时间戳f(x),然后我们建立反图Gt,接着根据倒序的时间戳来dfs每个节点,每次dfs到的结点集合就是一个强联通分量.事实上这个算法的思想和拓扑排序类似. 我们来证明它(注意这里面的图指原图,而不是反图): 引理:对于G中的两个强联通分量C和C',若点u属于C,点v属于C',且

[图论] 有向图强连通分量 (kosaraju算法,Tarjan算法)

记录自己的想法:在有向图中,如果一些顶点中任意两个顶点都能互相到达(间接或直接),那么这些顶点就构成了一个强连通分量,如果一个顶点没有出度,即它不能到达其他任何顶点,那么该顶点自己就是一个强连通分量.在用kosaraju算法和Tarjan算法求强连通分量的时候,就是给所有的顶点分组染色,同一种颜色的顶点在同一个强连通分量中,记录有多少种颜色(有多少个强联通分量),每个顶点属于哪种颜色(每个顶点在哪个强连通分量重).在同一个强连通分量中的所有顶点可以缩为一个顶点,然后根据缩点构造DAG(有向无环图