DFS序
DFS序,算法如其名就是用DFS搞的序。没有学过DFS的同学先去看看吧(基本中的基本)这个算法就是依靠DFS将一个树状图用线性结构进行排列。因为树形结构每次更新查找总是很费时间,如果我们可以用某种方法把它转变成线性结构就可以用线段树或者树状数组很轻松地记录了。
要将一个树进行线性排列,我们就需要记录每个根所含的叶子。这个问题可以用时间戳来搞定。(每次看到新词汇就害怕?其实这个戳就是个记录的数字,每次dfs一个点就++,当一个点dfs完所有子叶之后比较之前记录它自身的记录的数字就可以确定他的子叶个数和分别是什么了)
废话说太多。我们来看下这个图(转自网络侵删)
DFS一般从根节点1开始,每次深度优先遍历点,一般是【根,左叶到右叶】(这个叫什么序有同学知道告诉我我忘了)比如这个图的次序就是[2,4,7,1,3,6,5]
时间戳怎么实现呢?用两个数组in[] out[]和一个戳cnt,每dfs一个点i就cnt++并in[i]=cnt,遍历完子点再out[i]=cnt(cnt是全局变量)
实现
int time = 0;
inline void dfs(int x, int fa) {
in[x] = ++time;
num[time] = x;
for(int i = 0; i < G[x].size(); i++) {
int cnt = G[x][i];
if(cnt == fa) continue;
dfs(cnt, x);
}
out[x] = time;
}
当然,dfs序也可以变无向图为线性结构,就是把图变成一个生成树。
tarjan就是基于这个算法达到的。
#include<iostream> #include<cstdio> #include<vector> using namespace std; struct gh { int v,w; gh(){}; gh(int _v,int _w):v(_v),w(_w){} }; vector<gh> g[100]; int k,d[1000],n; int sech(int); int main() { freopen("dfs.in","r",stdin); int x,y,z; cin >> n; for(int i=1;i<=n;i++) { scanf("%d%d%d",&x,&y,&z); g[x].push_back(y); g[y].push_back(x); } sech(1); for(int i=1;i<=n+1;i++) cout<<d[i]; } int sech(int u) { int v; d[u]=++k; for(int j=0;j<g[u].size();j++) { v=g[u][j]; if(d[v]==0) sech(v); } }
原文:https://www.cnblogs.com/BrotherHood/p/12842000.html