您的位置:首页 > 其它

图论基础算法

2016-04-03 11:55 232 查看
这些东西本来去年就会的……然而由于太久没打(其实真相是整天都在浪),于是在某一天我惊奇地发现早已忘记……

首先,是有向图的强连通分量……我写的是tarjan算法(卧槽tarjan这人怎么这么6,splay,lca,强连通分量都跟他有关系)

这里有一道题目:codevs 2822(顺手把一年前没a的题a了)

强连通分量中边只有三种,一种是树边,一种是返祖边,还有一种不知道叫什么边(反正这种边都没用)

显然只有树边和返祖边有用

对于一个节点,他的颜色可能有三种,黑白灰,白表示这个节点还没有被访问过,灰表示在栈里,黑表示已出栈

我们需要两个数组:low数组用来记录他的子树的返祖边指向深度最浅的祖先的深度,dfn表示他的编号(也叫时间戳)

low(u)=

min{

dfn(u)

low(v) (u,v)为树边

dfn(v) (u,v)为返祖边

}

如果满足low(u)==dfn(u)那么说明u和当前栈里还没出栈的深度比u深的节点都属于一个强连通分量

什么?无向图的双连通分量?

一样的……只要记录上一个节点防止死循环就好了……

割点:把这个点去掉之后连通分量数量增加

桥:把这条边去掉之后连通分量数量增加

割点求法:有两种情况

1,根有超过两棵子树,此时根为割点

2,存在树边u,v,使得low(v)>=dfn(u)

桥求法:树边u,v,使得low(v)>dfn(u)

割点例题:poj1174

桥例题:hdu4738

强连通分量code:

void dfs(int now)

{

s.push(now);

low[now]=dfn[now]=++tot;

vis[now]++;

for (int ii=0;ii<g[now].size();ii++) if (!vis[g[now][ii]]){

dfs(g[now][ii]);

low[now]=min(low[now],low[g[now][ii]]);

}

else if (vis[g[now][ii]]==1){

low[now]=min(low[now],dfn[g[now][ii]]);

}

if (low[now]==dfn[now]){

if (!s.empty()){

int jb=s.top();s.pop();

ans++;

while (jb!=now){

fa[jb]=ans;

size[ans]++;

vis[jb]++;

jb=s.top();s.pop();

}

fa[jb]=ans;

size[ans]++;

vis[jb]++;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: