有向图强连通分支的Tarjan算法 数据结构与算法实习

该说的都在代码里了,老师给的模板不符合本菜鸡的要求啊只能手动扩充了,用的是邻接矩阵存储图,可以换成邻接表啥的可能快点

#include <iostream>
#include<stack>
#include<string.h>
using namespace std;
#define MAXL 1000
/*
例子:
6
7
0 1
0 4
0 5
1 2
2 3
3 0
4 0
*/
/*
例子:
8
10
0 1
1 2
2 3
2 1
3 0
0 4
0 5
5 6
6 7
7 5
*/
int d[MAXL], L[MAXL],visited[MAXL];
int index;//访问顺序
int s[MAXL];//栈
int t,Size;//栈顶和边的最大值
int edge[MAXL][MAXL];//邻阶矩阵存储边
int min(int a, int b) {
 return a > b ? b : a;
}
void tarjan(int u) {
 if (visited[u]) {//已经访问过就跳过
  return;
 }
 d[u] = L[u] = ++index;//初次访问设置
 s[t++] = u;//存入栈
 visited[u] = 1;//标记访问(不需要在函数末尾恢复0)
 for (int i = 0; i < Size; i++) {//遍历始点为u的边
  if (edge[u][i]) {//有这条边
   if (!visited[i]) {//这条边的终点已经访问过就没用,没访问过则进行深搜
    tarjan(i);
    L[u] = min(L[u], L[i]);
   }
   else {
    L[u] = min(L[u], d[i]);
   }
  }
 }
 if (d[u] == L[u]) {//找到一个强连通分支始点(即DFS最早访问的点)后输出
  cout<<"帅:"<<endl;
  int out0 = -1;
  out0 = s[--t];
  if (out0 == u) {
   cout << out0 << endl;
  }
  else {
   while (out0 != u) {
    out0 = s[t--];
    cout << out0 << "  ";
   }
   cout << endl;
  } 
 }
}
int main()
{
 cin >> Size;//顶点数
 memset(d, 0, sizeof(d));
 memset(L, 0, sizeof(L));
 memset(s, 0, sizeof(s));
 memset(edge, 0, sizeof(edge));
 memset(visited, 0, sizeof(visited));
 int m, a, b;
 cin >> m;
 while (m--) {
  cin >> a >> b;
  edge[a][b] = 1;
 }
 for (int i = 0; i < Size; i++) {
  tarjan(i);//全部访问查找
 }
}
发布了8 篇原创文章 · 获赞 1 · 访问量 111

猜你喜欢

转载自blog.csdn.net/weixin_41087003/article/details/103724590
今日推荐