强连通分支

摘要:寻找强连通分支,利用构造深度搜索优先树的办法,找到有向图的强连通分支.

(1)基本思路:[1]首先利用深度搜索优先找到一颗深度搜索优先树.如果该树不包含所有的节点,那么对剩下的节点继续进行搜索.直到所有节点都被访问,这时候得到深度优先搜索树形成的森林.

[2]在搜索过程中对所有的节点进行编号(后序遍历).
[3]将该图进行反向,然后重新进行搜索,每次搜索的起点都找一个没有被访问的顶点中编号最低的点.
[4]第二次搜索中所获得的所有树就是强连通分支.

(2)算法分析:

[1]强连通分支应该是两次深度搜索优先树的交集,设点集合S同时存在于两次的深度优先搜索树A(根为x),B(根为y)中,那么对于点集中任何两点m,n,它们都是可以互相到达的.
[2]首先x可以到达A中的任何一点,那就意味着x->m,x->n.同时x在B中是根,因为每次搜索都是从编号最高的开始,x一定是该树中编号最高的(后序遍历),因此x就是y.那么对于B,x可以到达m,n.因为该树是反转图的生成树,那么在实际图中一定有,m->x,n->x;所以m,n可以通过x进行中转互相到达对方.
#include "stdafx.h"
#include "string.h"
#include "图论ADT.h"
static bool Isvisited[Number] = {false};
void Reverse (Graph G,Graph Gr)//对图进行反转
{
    int i = 0,v,w;
    List L;
    Initialize(Gr);
    for(;i<=Number-1;i++)
    {
        L = G[i]->Next; 
       while(L!=NULL)
       {
           v = L->Element;
           w = i;
           Insert(Gr[v],w);
           L = L->Next;
       }
    }
}
void FindForest(Graph G,int start,int &Numvisited,int & Index,int * Indexarray)//每次搜索得到一棵新的树
{
    int v = G[start]->Element,w;
     printf("%d ",v);
     Isvisited[v] = true;
    Numvisited ++;//又访问一个
    List L = G[start]->Next;
    while(L!=NULL)
    {
        w = L->Element;
        if (Isvisited[w] == false )//未访问
        {
            FindForest(G,w,Numvisited,Index,Indexarray);
        }
        L = L->Next;
    }   
    Indexarray[start] = Index++;
}
int FindNewNonvisited(bool *Isvisited)
{
    int i = 0;
    while(Isvisited[i] == true)
    {
        i++;
    }
    return i;
}
int Findnewvertex_highestIndex(bool* Isvisited,int * indexarray)
{
    //获得m没有访问的节点中编号最高的
    int i = -1,highest_index = 0,mark;
    while(1)
    {
    while(Isvisited[++i] == true){}
      if(i == 10)
          break;

       if (indexarray[i] >= highest_index)
      {
        highest_index = indexarray[i];
            mark = i;
      }
    }
    return mark;
}
void Findstrongconnect_drive(Graph G,int start)//驱动例程
{
    //获得强连通分支
    int Numvisited = 0;
    int Index = 0;//编号
    int Indexarray[Number];
    Graph Gr;
    while(Numvisited < Number)//只要还没搜索过所有节点就继续搜索
    {
    FindForest(G,start,Numvisited,Index,Indexarray);//找到新森林
    start = FindNewNonvisited(Isvisited);//找到下一次搜索起点
      }
    Reverse(G,Gr);//将邻接表反转
//第二次进行深度优先搜索,每次都从G的第一棵深度搜索优先树的根开始

    Numvisited = 0;
    memset(Isvisited,0,sizeof(Isvisited));
    while(Numvisited < Number)
    {   
        puts("\n");//对强之间连通分支进行间隔
        start = Findnewvertex_highestIndex(Isvisited,Indexarray);//每次都从编号最高的地方搜索起
        FindForest(Gr,start,Numvisited,Index,Indexarray);
    }
}

主函数:

int _tmain(int argc, _TCHAR* argv[])
{
    Graph G,Gr;
    Initialize(G);
    Insert(G[0],1);
    Insert(G[0],3);
    Insert(G[1],2);
    Insert(G[1],5);
    Insert(G[2],0);
    Insert(G[2],3);
    Insert(G[2],4);
    Insert(G[3],4);
    Insert(G[5],2);
    Insert(G[6],5);
    Insert(G[6],7);
    Insert(G[7],5);
    Insert(G[7],9);
    Insert(G[8],7);
    Insert(G[9],8);
    Reverse(G,Gr);
    int Indexarray[Number];
    int start = 1 ,Index = 0 ,Numvisited = 0;
    Findstrongconnect_drive(G,1);
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值