【数据结构】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直接做,先采用 ...
随机推荐
- [译]git push
push就是把你本地仓储的commit传到远程仓储中去. 用法 git push <remote> <branch> push指定的分支到<remote>中去. ...
- Tomcat 6 --- 使用Jasper引擎解析JSP
熟悉JAVA web开发的朋友都知道JSP会被转换成java文件(预编译),然后编译成class使用,即按照JSP-->java-->class的过程进行编译. 由于JVM只认识class ...
- 基础知识系列☞IList ←vs→ List
原文地址→http://www.cnblogs.com/zbphot/archive/2011/11/04/2235933.html IList接口→表示可按照索引单独访问的对象的非泛型集合. ILi ...
- 【Bootstrap】Bootstrap和Java分页-第二篇
目录 关于此文 配置xml-pager.tld 分页控件-Pager 分页action集成类-BaseController 实例-Dao 实例-service 实例-action 实例-JSP 实例- ...
- java 练手 谁是最好的Coder
Problem A 谁是最好的Coder 时间限制:1000 ms | 内存限制:65535 KB 描述 计科班有很多Coder,帅帅想知道自己是不是综合实力最强的coder. 帅帅喜欢帅,所 ...
- PHP基础Mysql扩展库
mysql扩展库操作步骤如下: 1.连接数据库 2.选择数据库 3.设置操作编码 4.发送指令sql,并返回结果集 ddl:数据定义语句 dml:数据操作语句 dql:数据查询 ...
- 【PHP面向对象(OOP)编程入门教程】2.什么是类,什么是对象,类和对象这间的关系
类的概念:类是具有相同属性和服务的一组对象的集合.它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...
- loadrunner-27796错误寻求解决办法
Action.c(58): Error -27796: Failed to connect to server "www.baidu.com:80": [10048] Addres ...
- jQuery Ajax无刷新操作一般处理程序 ashx
//前台实例代码 aspx文件 <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="ser ...
- 21个免费的UI设计工具和资源网站,不管是web,js,android都
本帖最后由 hua631150873 于 2014-9-12 18:26 编辑 Lumzy 官方地址:http://www.lumzy.com/ Lumzy是一个网站应用和原型界面制作工具.使用Lum ...