用DFS进行拓扑排序
求强连通分量:kosaraju's algorithm 这篇例文比较好 http://scienceblogs.com/goodmath/2007/10/30/computing-strongly-connected-c/
Key Lemma:
-----------------------------------------------------------
Programming Question-4
-------------------------------------------------------这个求SCC的思路参考上面kosaraju
我的代码,编译成功,第一次运行时在DFS的时候栈溢出。据前辈的修改意见有两种方法:
1.在VS里把栈的默认大小调大 http://www.1point3acres.com/bbs/thread-30666-3-1.html (我用的这个)
2.使用iterative DFS http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search
注意找出结果里的前5个大SCC,我刚开始用的QuickSort,结果运行一个小时没出结果(复杂度是n * log n);后来思考下只用遍历一遍,找出前5大的数就可以不用排序,就自己写了个TopFive的函数找出前5大数目记录在一个数组里,速度提高了很多,只几分钟就出了正确答案。
网上有人用了partial_sort来解决这个问题。目前还没理解好怎么用partial_sort,貌似很高深的样子
#include <stdio.h>
#include <tchar.h>
#include <vector>
#include <fstream>
#include <string>
#include <stack>
#include <iostream>
using namespace std;
#define MAX 875714
struct node {
int n;
bool visited;
vector<int> toNode;
vector<int> fromNode;
int SCC;
};
node Graph[MAX + 1];
stack<int> order;
int SCC_num = 0;
vector<int> SCC;
int top[6] = { 0 };
void init_graph() {
for(int i = 0; i < MAX + 1; i++) {
Graph[i].n = i;
Graph[i].visited = false;
}
}
void read_data(char * path) {
int from, to;
FILE * fp;
fp = fopen(path, "r");
if(fp == NULL) {
cout<<"FILE OPEN FAILED!"<<endl;
return;
} else {
// Set pointer to beginning of file:
fseek( fp, 0L, SEEK_SET );
}
while( fscanf(fp,"%d %d", &from, &to) > 0) {
Graph[from].toNode.push_back(to);
Graph[to].fromNode.push_back(from);
}
}
void DFS_Graph(int i) {
if(Graph[i].visited == true) return;
Graph[i].visited = true;
for(int k = 0; k < Graph[i].toNode.size(); k++) {
DFS_Graph(Graph[i].toNode[k]);
}
order.push(i);
return;
}
void rDFS_Graph(int i) {
if(Graph[i].visited == false) return;
Graph[i].visited = false;
int index = 0;
for(int k = 0; k < Graph[i].fromNode.size(); k++) {
index = Graph[i].fromNode[k];
rDFS_Graph(index);
}
Graph[i].SCC = SCC_num;
SCC[SCC_num - 1]++;
return;
}
void TopFive() {
for(int i = 0; i < SCC.size(); i++) {
top[5] = SCC[i];
for(int j = 4; j >= 0; j--) {
if(top[j+1] > top[j]) {
int temp = top[j];
top[j] = top[j + 1];
top[j + 1] = temp;
} else break;
}
}
}
int main() {
init_graph();
read_data("SCC.txt");
//遍历DFS
for(int j = 1; j < MAX + 1; j++) {
if( !Graph[j].visited ) DFS_Graph(j);
}
//reverse DFS
while(!order.empty()) {
int index = order.top();
order.pop();
if(Graph[index].visited == true) {
SCC_num++;
SCC.push_back(0);
rDFS_Graph(index);
}
}
//找出SCC中前5大的元素
TopFive();
ofstream fout("out.txt");
for(int i = 0; i < 5; i++) {
fout<<top[i]<<endl;
cout<<top[i]<<endl;
}
fout.close();
return 0;
}