#include "stdafx.h"
#include
#include // 广度优先搜索中管理灰色顶点的先进先出队列
#include // 邻接表容器
#include
#include // INT_MAX
#include // 泛型算法sort的谓词版本进行拓扑排序
using namespace std;
enum COLOR {WHITE, GRAY, BLACK};
struct Vertex {
trueint no; // 结点序号
truestring name; // 结点名称
trueCOLOR color;
truevector* Adj; // 邻接表,包含所有满足条件(u, v)∈E的顶点v
true// 用于广度优先搜索
trueint distence; // 广度优先树中从s到v的路径长,对应于图G中从从s到v的一条最短路径长
trueVertex* parent; // 广度优先树中结点的父母
true// 用于深度优先搜索
trueVertex* child; // 深度优先树中结点的孩子,方便输出强联通分支,算是数据结构的扩张的一个应用。。。
trueint begin; // 顶点v第一次被发现时记下该时间戳
trueint finish; // 结束检查v的邻接表时记下该时间戳
};
// sort的谓词函数,用作拓扑排序
inline bool isLarge(const Vertex* v1, const Vertex* v2)
{
truereturn v1->finish > v2->finish;
}
class Graph {
public:
true// 构造邻接表
truevoid creatGraph();
trueinline void displayGraph() const;
true// 广度优先搜索
truevoid BFS(const int);
truevoid printPath(const int, const int) const;
true// 深度优先搜索
truevoid DFS();
truevoid DFSVisit(Vertex*);
trueinline void topologicalSort(); // 有向无回路图的拓扑排序
truevoid transposition(); // 转置
truevoid stronglyConnectedComponents(); // 强连通分支
private:
trueint time;
truevector vertexs; // 储存邻接表
};
void Graph::creatGraph()
{
trueint verNum;
truecout << "输入顶点数:";
truecin >> verNum;
truecout << "输入" << verNum << "个顶点的名称:";
truefor (int i = 0; i != verNum; ++i) {
truetrueVertex* newNode = new Vertex;
truetruenewNode->no = i + 1;
truetruecin >> newNode->name;
truetruevertexs.push_back(newNode);
true}
truefor (int i = 0; i != verNum; ++i) {
truetruevector* ivec = new vector;
truetruevertexs[i]->Adj = ivec;
truetruecout << "输入第" << i + 1 << "个结点" << vertexs[i]->name << "的邻接节点个数和序号:";
truetrueint j;
truetruecin >> j;
truetruewhile (j-- != 0) {
truetruetrueint k;
truetruetruecin >> k;
truetruetruevertexs[i]->Adj->push_back(k);
truetrue}
true}
}
void Graph::displayGraph() const
{
truefor (vector::const_iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter) {
truetruecout << (*iter)->no << " -> ";
truetruefor (vector::const_iterator adjIter = (*iter)->Adj->begin(); adjIter != (*iter)->Adj->end(); ++adjIter)
truetruetruecout << *adjIter << " -> ";
truetruecout << "NULL" << endl;
true}
}
void Graph::BFS(const int start)
{
trueVertex* startNode = vertexs[start - 1];
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter) {
truetruetrue(*iter)->color = WHITE;
truetruetrue(*iter)->distence = INT_MAX;
truetruetrue(*iter)->parent = NULL;
true}
truestartNode->color = GRAY;
truestartNode->distence = 0;
truequeue vertexsQueue;
truevertexsQueue.push(startNode);
truewhile (!vertexsQueue.empty()) {
truetrueVertex* thisNode = vertexsQueue.front();
truetruevertexsQueue.pop();
truetruefor (vector::iterator iter = thisNode->Adj->begin(); iter != thisNode->Adj->end(); ++iter)
truetruetrueif (vertexs[*iter - 1]->color == WHITE) {
truetruetruetruevertexs[*iter - 1]->color = GRAY;
truetruetruetrue++vertexs[*iter - 1]->distence;
truetruetruetruevertexs[*iter - 1]->parent = thisNode;
truetruetruetruevertexsQueue.push(vertexs[*iter - 1]);
truetruetrue}
truetruethisNode->color = BLACK;
true}
}
void Graph::printPath(const int start, const int end) const
{
trueif (start == end)
truetruecout << "The path from " << start << " to " << end << " is " << start;
trueelse if (vertexs[end - 1]->parent == NULL)
truetruecout << "No path from " << start << " to " << end << " exist.";
trueelse {
truetrueprintPath(start, vertexs[end - 1]->parent->no);
truetruecout << " -> " << end;
true}
}
void Graph::DFS()
{
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter) {
truetrue(*iter)->color = WHITE;
truetrue(*iter)->parent = NULL;
truetrue(*iter)->child = NULL;
true}
truetime = 0;
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter)
truetrueif ((*iter)->color == WHITE)
truetruetrueDFSVisit(*iter);
}
void Graph::DFSVisit(Vertex* thisNode)
{
truethisNode->color = GRAY;
truethisNode->begin = ++time;
truefor (vector::iterator iter = thisNode->Adj->begin(); iter != thisNode->Adj->end(); ++iter)
truetrue// 拓扑排序会打乱顺序
truetruefor (vector::iterator iter2 = vertexs.begin(); iter2 != vertexs.end(); ++iter2)
truetruetrueif ((*iter2)->no == *iter)
truetruetruetrueif ((*iter2)->color == WHITE) {
truetruetruetruetrue(*iter2)->parent = thisNode;
truetruetruetruetruethisNode->child = *iter2;
truetruetruetruetrueDFSVisit(*iter2);
truetruetruetrue}
truethisNode->color = BLACK;
truethisNode->finish = ++time;
}
void Graph::topologicalSort()
{
true// 通过比较finish时间,从而完成拓扑排序
truesort(vertexs.begin(), vertexs.end(), isLarge); // 排序算法的谓词版本,使用isLarge函数进行比较
}
void Graph::transposition()
{
truevector tmpVertexs;
truefor (int i = 0; i != vertexs.size(); ++i) {
truetrueVertex* newVertex = new Vertex;
truetruenewVertex->Adj = new vector;
truetruetmpVertexs.push_back(newVertex);
true}
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter)
truetruefor (vector::iterator adjIter = (*iter)->Adj->begin(); adjIter != (*iter)->Adj->end(); ++adjIter)
truetruetruetmpVertexs[*adjIter - 1]->Adj->push_back(iter - vertexs.begin() + 1);
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter)
truetrue(*iter)->Adj = tmpVertexs[iter - vertexs.begin()]->Adj;
}
void Graph::stronglyConnectedComponents()
{
trueDFS(); // 第一轮深度优先搜索,计算finish时间戳
truetransposition(); // 转置vertexs
truetopologicalSort(); // 根据finish时间戳进行拓扑排序
truecout << endl << "转置后:" << endl;
truedisplayGraph();
trueDFS(); // 第二轮深度优先搜索,构造强联通分支
true// 输出强连通分支(深度优先森林),森林中的每一颗树就是一个强连通分支
trueint i = 1;
truefor (vector::iterator iter = vertexs.begin(); iter != vertexs.end(); ++iter)
truetrueif ((*iter)->parent == NULL && (*iter)->Adj->size() != 0) {
truetruetruecout << "第" << i++ << "组强联通分支:";
truetruetruecout << "no << ":" << (*iter)->name << ">";
truetruetrueVertex* iter2 = *iter;
truetruetruewhile (iter2->child != NULL) {
truetruetruetrueiter2 = iter2->child;
truetruetruetruecout << "no << ":" << iter2->name << ">";
truetruetrue}
truetruetruecout << endl;
truetrue}
}
int main()
{
trueGraph graph;
truegraph.creatGraph();
truegraph.displayGraph();
truegraph.stronglyConnectedComponents();
truesystem("pause");
truereturn 0;
}