用十字链表结构写的,根据数据结构书上的描述和自己的理解实现。但理解的不透彻,所以不知道有没有错误。但实验了几个都ok.

#include <iostream>
#include <vector>
using namespace std; //有向图十字链表表示
#define MAX_VERTEX_NUM 20 typedef struct ArcBox{
int tailvex, headvex; //该弧尾和头顶点的位置
struct ArcBox *hlink, *tlink; //分别指向弧头相同和弧尾相同的弧的链域
}ArcBox; typedef struct VexNode{
int data;
ArcBox *firstin, *firstout;//分别指向该顶点的第一条入弧和出弧
}VexNode; typedef struct{
VexNode xlist[MAX_VERTEX_NUM]; //表头向量
int vexnum, arcnum; //有向图的顶点数和弧数
}OLGraph; //定位顶点在xlist中的位置
int LocateVex(OLGraph G, int data)
{
for(int i = ; i < G.vexnum; i++)
{
if(G.xlist[i].data == data)
{
return i;
}
}
cout << "error the vertex "<< data << " is not in the list"<<endl;
return -;
} //有向图十字链表创建
void CreateDG(OLGraph &G)
{
cout << "please input the number of vertex, the number of arc:";
cin >> G.vexnum >> G.arcnum; for(int i = ; i < G.vexnum; i++)
{
cout << "please input vertex data:";
cin >> G.xlist[i].data; G.xlist[i].firstin = NULL; //初始化指针
G.xlist[i].firstout = NULL;
} for(int k = ; k < G.arcnum; k++)
{
int v1, v2; //弧的尾和头
cout << "please input the tail and head vertex of each tail:";
cin >> v1 >> v2; int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
ArcBox * p = new ArcBox;
p->headvex = j;
p->tailvex = i;
p->hlink = G.xlist[j].firstin;
p->tlink = G.xlist[i].firstout; G.xlist[j].firstin = p;
G.xlist[i].firstout = p;
}
} //单向深度优先搜索
//输入: 图G, 开始遍历点v, 遍历标志visited, 遍历方向dir 0 表示从尾向头遍历 1表示从头到尾遍历, vecor存放跳出遍历的顺序
void DFS(OLGraph G, int v, int * visited, int dir, vector<int> * vec)
{
visited[v] = ;
(*vec).push_back(v);
if(dir == ) //从尾向头遍历
{
ArcBox * w = G.xlist[v].firstout;
while(w != NULL ) //注意 这里的while
{
if(visited[w->headvex] == )
{
w = w->tlink;
}
else//未访问过该点 递归遍历该点
{
DFS(G, w->headvex, visited, dir, vec);
w = w->tlink;
}
}
}
else //从头向尾遍历
{
ArcBox * w = G.xlist[v].firstin;
while(w != NULL)//查找下一个遍历点
{
if((visited[w->tailvex]) == )
{
w = w->hlink;
}
else//未访问过该点 递归遍历该点
{
DFS(G, w->tailvex, visited, dir, vec);
w = w->hlink;
}
}
}
} //查找有向图强连通分量
vector<vector<int>> FindConnectedPart(OLGraph G)
{
vector<vector<int>> ConnectedPart;
vector<vector<int>> finished;
int* visited = new int[G.vexnum];
memset(visited, , G.vexnum * sizeof(int)); //初始化为全部没有访问过 //从尾向头遍历
for(int v = ; v < G.vexnum; v++)
{
if(visited[v] == ) //没有被访问过
{
vector<int> vec;
DFS(G, v, visited, , &vec);
finished.push_back(vec);
}
} //从头向尾遍历
memset(visited, , G.vexnum * sizeof(int));
vector<int>::iterator it;
vector<vector<int>>::iterator it2;
int* find = new int[G.vexnum]; //find标识顶点实际上是否被查找过
for(int i = ; i < G.vexnum; i++)
{
find[i] = ;
visited[i] = ;
}
for(it2 = finished.begin(); it2 < finished.end(); it2++)
{
//已经遍历过的部分visited不变,即都是1; find[i]= 0的表示本次遍历时不遍历结点i,为了跳过i,设它们的visited[i]=1; 但实际上,它们还没有被访问到
//比如从尾到头遍历时得到两个分量 (1,2,3,4)(5)
//那么为了找到重连通分量,从头到尾遍历4,3,2,1时不应该经过5 即可能从头到尾遍历时的分量是(1 2 3 5)(4)
// 但实际上重连通分量为(1,2,3)(4)(5)三个
for(it = it2->begin(); it < it2->end(); it++)
{
visited[*it] = ; //只把本次遍历考虑到的顶点的visited设为0,其他为1,就不会加人遍历了
find[*it] = ;
} for(it = it2->begin(); it < it2->end(); it++)
{
if(visited[*it] == ) //没有被访问过
{
vector<int> vec;
DFS(G, *it, visited, , &vec);
ConnectedPart.push_back(vec);
}
}
} //输出重连通分量
int n = ;
cout << "重连通分量有:" << endl;
for(it2 = ConnectedPart.begin(); it2 < ConnectedPart.end(); it2++)
{
cout << ++n << ":";
for(it = it2->begin(); it < it2->end(); it++)
{
cout << G.xlist[*it].data << " ";
}
cout<< endl;
} delete [] visited;
delete [] find;
return ConnectedPart;
} int main()
{
OLGraph G;
CreateDG(G);
FindConnectedPart(G); return ;
}

http://blog.csdn.net/wsniyufang/article/details/6604458里面有将更好的算法。我还没看。

【数据结构】DFS求有向图的强连通分量的更多相关文章

  1. 图论-求有向图的强连通分量(Kosaraju算法)

    求有向图的强连通分量     Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...

  2. Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量

    在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...

  3. Tarjan算法 求 有向图的强连通分量

    百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...

  4. Tarjan算法求有向图的强连通分量

    算法描述 tarjan算法思想:从一个点开始,进行深度优先遍历,同时记录到达该点的时间(dfn记录到达i点的时间),和该点能直接或间接到达的点中的最早的时间(low[i]记录这个值,其中low的初始值 ...

  5. (转)求有向图的强连通分量个数(kosaraju算法)

    有向图的连通分量的求解思路 kosaraju算法 逛了很多博客,感觉都很难懂,终于找到一篇能看懂的,摘要记录一下 原博客https://www.cnblogs.com/nullzx/p/6437926 ...

  6. 求有向图的强连通分量个数 之 Kosaraju算法

    代码: #include<cstdio> #include<cstring> #include<iostream> using namespace std; ][] ...

  7. 图->连通性->有向图的强连通分量

    文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...

  8. DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)

    一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...

  9. uva11324 有向图的强连通分量+记忆化dp

    给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以). 因为整张图可能存在环路,所以不好使用dp直接做,先采用 ...

随机推荐

  1. Ruby注意事项

    在Ruby中只有false和nil是'假', 其余都是真(0也是真)

  2. XDU 1160 - 科协的数字游戏I

    Problem 1160 - 科协的数字游戏I Time Limit: 1000MS   Memory Limit: 65536KB   Difficulty: Total Submit: 184   ...

  3. 64.SHELL

    SHELL 1. crontab定时器 编辑使用crontab -e 一共6列,分别是:分 时 日 月 周 命令 查看使用crontab -l 删除任务crontab -r 查看crontab执行日志 ...

  4. Ubuntu 12 编译安装 PHP 5.4 及 问题汇总

    参考先前的文章:Ubuntu 14 编译安装 PHP 5.4.45 + Nginx 1.4.7 + MySQL 5.6.26 笔记 安装过程: ############################ ...

  5. sja1000芯片can驱动程序

    应用层使用socketCan的方法:http://pan.baidu.com/s/1ntsvbb7#path=%252Floongson1%252Ftools%252Fcan 功能:对can驱动程序的 ...

  6. java之String

    一.构造器 package com.string; import java.io.UnsupportedEncodingException; import java.nio.charset.Chars ...

  7. 关于CSS的优先级,CSS优先级计算

    原则一: 继承不如指定原则二: #id > .class > 标签选择符原则三:越具体越强大原则四:标签#id >#id ; 标签.class > .class CSS优先级权 ...

  8. View和ViewImage设置图片

    1.view类的设置背景android:background --setBackgroundResource(int) --A drawable to use as the background. s ...

  9. Two Strings Are Anagrams

    Write a method anagram(s,t) to decide if two strings are anagrams or not. 判断两个字符串里的字符是否相同,也就是是否能够通过改 ...

  10. centos 修改DNS,网关,IP地址

    1.CentOS 修改DNS 修改对应网卡的DNS的配置文件 # vi /etc/resolv.conf  修改以下内容 nameserver 8.8.8.8 #google域名服务器 nameser ...