强连通分量分解

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

using namespace std;
const int N = 10000 + 10;
const int M = 50000 + 10;

int n, m;
int head1[N], tot1, head2[N], tot2;
bool vis[N];
vector<int> v; //后序访问顺序的顶点列表
int cmp[N]; //所属强连通分量的拓扑序

struct Edge
{
    int v, next;
}e1[M], e2[M];

void init()
{
    v.clear();
    tot1 = tot2 = 0;
    memset(head1, -1, sizeof(head1));
    memset(head2, -1, sizeof(head2));
}

void adde(int *head, Edge *edge, int &tot, int u, int v)
{
    edge[tot].v = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void dfs(int u)
{
    vis[u] = true;
    for(int i=head1[u]; i!=-1; i=e1[i].next)
    {
        int v = e1[i].v;
        if(!vis[v]) dfs(v);
    }
    v.push_back(u);
}

void rdfs(int u, int k)
{
    vis[u] = true;
    cmp[u] = k;
    for(int i=head2[u]; i!=-1; i=e2[i].next)
    {
        int v = e2[i].v;
        if(!vis[v]) rdfs(v, k);
    }
}

void disp(int *head, Edge *edge) //显示邻接表详细情况
{
    for(int i=1; i<=n; i++)
    {
        printf("%d : ", i);
        for(int j=head[i]; j!=-1; j=edge[j].next)
            cout<<edge[j].v<<"  ";
        cout<<endl;
    }
}

int SCC()//查找出有多少个强连通分量
{
    memset(vis, 0, sizeof(vis));
    for(int i=1; i<=n; i++)
        if(!vis[i]) dfs(i);

    memset(vis, 0, sizeof(vis));
    int k=0;
    for(int i=v.size()-1; i>=0; i--)
        if(!vis[v[i]])
       rdfs(v[i], k++);

    return k;
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        int u, v;
        init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d", &u, &v);
            adde(head1, e1, tot1, u, v); //正向图
            adde(head2, e2, tot2, v, u); //反向图
        }
        disp(head1, e1);
        cout<<endl;
        disp(head2, e2);
        int ans = SCC();
        printf("%d\n", ans);
    }
    return 0;
}

/*

6 7
1 2
2 3
2 4
3 4
4 5
5 3
5 6

*/

时间: 2024-11-08 23:13:07

强连通分量分解的相关文章

【强连通分量分解】

摘自<挑战程序设计>4.3.1 [强连通分量分解原理] 对于一个有向图顶点的子集S,如果在S内任取两个顶点u和v,都能找到一条从u到v的路径,那么就称S是强连通的.如果在强连通的顶点集合S中加入其他任意顶点集合后,它都不再是强连通的,那么就称S是原图的一个强连通分量(SCC: Strongly Connected Component).任意有向图都可以分解成若干不相交的强连通分量,这就是强连通分量分解.把分解后的强连通分量缩成一个顶点,就得到了一个DAG(有向无环图). 强连通分量分解可以通过

强连通分量分解 tarjan算法 (hdu 1269)

题意: 给出一个有n个点m条边的有向图,判断该图是否只有一个强连通分量. 限制: 0 <= N <= 10000 0 <= M <= 100000 思路: tarjan算法分解强连通分量. /*强连通分量分解 tarjan算法 (hdu 1269) 题意: 给出一个有n个点m条边的有向图,判断该图是否只有一个强连通分量. 限制: 0 <= N <= 10000 0 <= M <= 100000 */ #include<iostream> #inc

POJ(2186)强连通分量分解

#include<cstdio> #include<vector> #include<cstring> using namespace std; const int MAX_N=10005; vector<int> G[MAX_N]; vector<int> rG[MAX_N];//存储边反向之后的图 vector<int> PostOrder;//存储图的后序遍历 int V,E; bool used[MAX_N]; int com

POJ2186(强连通分量分解)

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35035   Accepted: 14278 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &

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

poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且可以传递, 即1欢迎2不代表2欢迎1, 但是如果2也欢迎3那么1也欢迎3. 求被所有牛都欢迎的牛的数量. 限制: 1 <= N <= 10000 1 <= M <= 50000 思路: Kosaraju算法, 看缩点后拓扑序的终点有多少头牛, 且要判断是不是所有强连通分量都连向它. Kosaraju算法,分拆完连通分量后,也完成了拓扑序. /*poj 2186

强连通分量tarjan模板复习

对于一个有向图定点的子集,在该子集中任取两点u与v,都能找到一条从u到v的路径,则称该子集是强连通的.若该集合加入到任意点集中,它都不再强连通,则称这个子集是原图的一个强连通分量.任意一张图都可以分解成若干个不相交的强连通分量.这是强连通分量分解.把分解后的强连通分量缩成一个顶点,就可以得到一个有向无环图. 如图: 求一张图的强连通分量的个数,常用tarjan算法,它是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈

poj2186Popular Cows(Kosaraju算法--有向图的强连通分量的分解)

1 /* 2 题目大意:有N个cows, M个关系 3 a->b 表示 a认为b popular:如果还有b->c, 那么就会有a->c 4 问最终有多少个cows被其他所有cows认为是popular! 5 6 思路:强连通分量中每两个节点都是可达的! 通过分解得到最后一个连通分量A, 7 如果将所有的强连通分量看成一个大的节点,那么A一定是孩子节点(因为我们先 8 完成的是父亲节点的强连通分量)! 最后如果其他的强连通分量都可以指向A,那么 9 A中的每一个cow都会被其他cows所

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

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

POJ_2186_Popular Cows_强连通分量

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 30680   Accepted: 12445 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &