您的位置:首页 > 其它

强连通分量分解

2015-06-13 12:01 357 查看
#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
, tot1, head2
, tot2;
bool vis
;
vector<int> v; //后序访问顺序的顶点列表
int cmp
; //所属强连通分量的拓扑序

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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: