一、数据集形式
其中:1595446(节点个数)
0(起始边) 1(终边)
二、数据集
三、实现代码
Base.h
#pragma once
#include "Tree.h"
class CBase
{
public:
CBase(CTree *t, int l);
~CBase();
int length;
CTree* tree;
};
Base.cpp
#include "stdafx.h"
#include "Base.h"
CBase::CBase(CTree *t, int l)
{
tree = t;
length = l;
}
CBase::~CBase()
{
}
Tree.h
#pragma once
#include "TreeNode.h"
class CTree
{
public:
CTree();
~CTree();
int value;
int state;//状态,0表示未被访问过,1表示初次访问,2表示访问完成
CTreeNode *next;
};
TreeNode.cpp
#pragma once
class CTreeNode
{
public:
CTreeNode();
~CTreeNode();
int value;
CTreeNode *next;
};
Kasaraju.h
#pragma once
#include "Base.h"
#include "Ftime.h"
#include <fstream>
class CKasaraju : public CBase
{
public:
CKasaraju(CTree *t, int l);
~CKasaraju();
void GetResult();
void DfsVisit(CTree*tNode);
CTree * Reverse();
void G_DfsVisit(CTree*tNode);
CTree *G;
int *finish;
int count;
};
Kasaraju.cpp
#include "stdafx.h"
#include "Kasaraju.h"
#include "Base.h"
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
CKasaraju::CKasaraju(CTree *t, int l):CBase(t, l)
{
}
CKasaraju::~CKasaraju()
{
}
void CKasaraju::GetResult()
{
/*1、深度优先搜索,找到完成时间的finish值*/
finish = new int[length];
count = 0;
for (int i = 0; i < length; i++)
{
if (tree[i].state == 0)
DfsVisit(&tree[i]);
}
/*2、G为tree的转置*/
G = Reverse();
/*3、找出所有的强连通分量*/
int ij = 0;
for (int i = count; i >= 0; i--) //G图的深度优先
{
ij++; //记录强连通分量个数
if(G[finish[count]].state == 0)
G_DfsVisit(&G[finish[i]]);
}
cout << "共" << ij << "组强连通分量";
}
void CKasaraju::G_DfsVisit(CTree*tNode)
{
G[tNode->value].state = 1;
CTreeNode *p = tNode->next;
while (p != NULL)
{
if (G[p->value].state == 0)
{
G_DfsVisit(&G[p->value]);
}
p = p->next;
}
}
void CKasaraju::DfsVisit(CTree*tNode)
{
tNode->state = 1;
CTreeNode *p = tNode->next;
while (p != NULL)
{
if (tree[p->value].state == 0)
{
DfsVisit(&tree[p->value]);
}
p = p->next;
}
tNode->state = 2;
finish[count++] = tNode->value;
}
CTree * CKasaraju::Reverse()
{
CTree *G = new CTree[length];
//为树赋初值
for (int i = 0; i < length; i++)
{
G[i].next = NULL;
G[i].state = 0;
G[i].value = i;
}
for (int i = 0; i < length; i++)
{
CTreeNode *p = tree[i].next;
while (p != NULL)
{
//新建一个节点挂到G的反向图上
CTreeNode *nt = new CTreeNode();
nt->value = i;
//头插法,挂载到G上
nt->next= G[p->value].next;
G[p->value].next = nt;
//查找下一个节点
p = p->next;
}
}
delete[]tree;
return G;
}
main函数
// SCC.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Tree.h"
#include "Kasaraju.h"
#include "time.h"
#include <fstream>
#include <string>
#include<iostream>
#include<stack>
#include "Tarjan.h"
using namespace std;
CTree* createTree(char* filename,int &length)
{
CTree *tree;
ifstream ReadFile;
int temp;
ReadFile.open(filename, ios::in);//ios::in 表示以只读的方式读取文件
ReadFile >> length;//第一个字符是数组长度
tree= new CTree[length];
//为树赋初值
for (int i = 0; i < length; i++)
{
tree[i].next = NULL;
tree[i].value = i;
tree[i].state = 0;
}
CTreeNode *nt;
while(!ReadFile.eof()) //按空格读取,遇到空白符结束
{
nt=new CTreeNode; //读出的数据新建一个节点
ReadFile >> temp >> (nt->value);
nt->next = tree[temp].next;
tree[temp].next = nt;
}
return tree;
}
int main()
{
int length;
double useTime;
clock_t start, finish;
//读取了文本中的内容,并根据建立其邻接链表
CTree *tree = createTree(PATH, length);
//Kasarju方法求强连通分量
CKasaraju method1(tree, length);
start = clock();
method1.GetResult();
finish = clock();
useTime = (double)(finish - start) / CLOCKS_PER_SEC * 1000;
printf("%f 毫秒\n", useTime);
system("pause");
return 0;
}