tarjan模板及应用

来源:互联网 发布:网络成瘾调查问卷 编辑:程序博客网 时间:2024/05/22 05:27

tarjan的用处很多

对有向图:求强联通分量

对无向图:求割点、求桥。特别地,可以分离仙人掌图里的环

先贴一个看到不错的博客:点击打开链接

//有向图强联通分量void  tarjan(int  x){dfn[x] = low[x] = ++times;S.push(x);f[x] = true;for  (int  i = head[x];i;i = nex[i])if  (!dfn[des[i]]){tarjan(des[i]);low[x] = min(low[x], low[des[i]]);}else  if  (f[des[i]])  low[x] = min(low[x], dfn[des[i]]);if  (dfn[x] == low[x]){//block in stack Snn++;int  y;do{y = S.top();S.pop();val[nn] ++;f[y] = false;blo[y] = nn;}while  (y != x)}}

//无向图求割点或桥,注意割点的判断条件void  tarjan(int  x,int  pre){dfn[x] = low[x] = ++times;int  child_cnt = 0;bool  flg = false;for  (int  i = head[x];i;i = nex[i]){int  y = des[i];if  (!dfn[y]){S.push(i);//edges in stacktarjan(y, i^1);low[x] = min(low[x], low[y]);if  (low[y] > dfn[x]){}//(x, y) is bridgeif  (low[y] >= dfn[x]){//point xflg = true;   }child_cnt ++;}else  low[x] = min(low[x], dfn[y]);}if  (pre == 0 && child_cnt > 1)  cnt++;if  (pre && flg)  cnt++;}

//仙人掌图(只有简单环,一条边最多出现在一个环里)求环,例:HDU6041dfn[x] = low[x] = ++times;for  (int  i = head[x];i;i = nex[i]){int  y = des[i];if  (!dfn[y]){S.push(i);dfs(y, i^1);low[x] = min(low[x], low[y]);if  (low[y] >= dfn[x]){int  j;T.resize(0);do{j = S.top();S.pop();T.PB(w[j]);}while  (j != i);}}else  if  (i != pre && dfn[y] < dfn[x])S.push(i), low[x] = min(low[x], dfn[y]);}}

一些细节:1、如果栈内存边,应该top从2开始标号

                    2、割点的判断条件有两种:如果是根,只需要实边的儿子数大于一,否则需要有满足low[y]>=dfn[x]这个条件的实边儿子。