【数据结构】DFS求有向图的强连通分量
用十字链表结构写的,根据数据结构书上的描述和自己的理解实现。但理解的不透彻,所以不知道有没有错误。但实验了几个都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求有向图的强连通分量的更多相关文章
- 图论-求有向图的强连通分量(Kosaraju算法)
求有向图的强连通分量 Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...
- Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量
在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...
- Tarjan算法 求 有向图的强连通分量
百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...
- Tarjan算法求有向图的强连通分量
算法描述 tarjan算法思想:从一个点开始,进行深度优先遍历,同时记录到达该点的时间(dfn记录到达i点的时间),和该点能直接或间接到达的点中的最早的时间(low[i]记录这个值,其中low的初始值 ...
- (转)求有向图的强连通分量个数(kosaraju算法)
有向图的连通分量的求解思路 kosaraju算法 逛了很多博客,感觉都很难懂,终于找到一篇能看懂的,摘要记录一下 原博客https://www.cnblogs.com/nullzx/p/6437926 ...
- 求有向图的强连通分量个数 之 Kosaraju算法
代码: #include<cstdio> #include<cstring> #include<iostream> using namespace std; ][] ...
- 图->连通性->有向图的强连通分量
文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...
- DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)
一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...
- uva11324 有向图的强连通分量+记忆化dp
给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以). 因为整张图可能存在环路,所以不好使用dp直接做,先采用 ...
随机推荐
- [译]Mongoose指南 - Document
更新 有几种方式更新document. 先看一下传统的更新方法 Tank.findById(id, function(err, tank){ if(err) return handleError(er ...
- INSTALL_FAILED_INSUFFICIENT_STORAGE(转发)
[2012-06-19 14:06:47 - Icontacts] Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE[2012-06-19 ...
- [转]C++模板学习
1. 模板的概念. 我们已经学过重载(Overloading),对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同.正确的调用重载函数.例如,为求两个数的最大值,我们定义MAX()函数 ...
- ggplo2学习笔记——基本图形类型
1.散点图:又称散点分布图,是以一个变量为恨坐标,另一个变量为纵坐标,利用散点(坐标点)的分布形态反映变量统计关系的一种图形.可以用来确认两个变量之间的关系.绘制自由曲线.矩阵关联分析等. 2.条形图 ...
- Linux 下复制(cp)目录时排除一个或者多个目录的方法
cp 貌似没有排除目录的功能,可以使用 rsync 命令来实现了,如: [案例] /home/52php目录里面有data目录,data目录里面有 a.b.c.d.e 五个目录,现在要把data目录里 ...
- CentOS 6.5 zabbix 3.0.4 SendEmail报警
官方介绍:http://caspian.dotconf.net/menu/Software/SendEmail/ 1.sendEmail部署 下载安装包到本地.解压 [root@localhost S ...
- (一)css代码积累——自己经常忘记,但是总记不住的代码
1.透明度设置 90%透明:filter:alpha(opacity=90);-moz-opacity:0.90;-khtml-opacity: 0.90;opacity: 0.90; 80%透明:f ...
- spring 部分配置内容备忘
1.spring定时器简单配置: <bean name="taskJob" class="com.netcloud.mail.util.TaskJob"& ...
- 三. 动态添加option选项
- mysql 时间戳 按周、日、月 统计方法 附 date格式
create_time时间戳格式 SELECT FROM_UNIXTIME(create_time,'%Y%u') weeks,COUNT(id) COUNT FROM role GROUP BY w ...