ps:本人太菜了,强连通分量是最近才开始上手写题的,勿喷。

part1:判断图是否联通

相信不用多说:dfs一遍或者并查集

如果你是普及选手:

dfs做法:

从任意一个点开始遍历整个图,如果所有点都被遍历一遍,就是联通的。

并查集:

把每个边的两个点并在一起,看看是否所有点被并到一个集合里了。


计算连通块也可以用以上方法解决。


part2:强连通分量

①:

什么是强连通分量?

“有向图强连通分量:在有向图G中,如果两个顶点 \(v_i\),\(v_j\) 间(\(v_i\) \(\neq\) \(v_j\))有一条从 \(v_i\)\(v_j\) 的有向路径,同时还有一条从 \(v_j\)\(v_i\) 的有向路径,则称两个顶点强连通 \((strongly\) \(connected)\)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量 \((strongly\) \(connected\) \(components)\)。”

说的通俗易懂一些:

一张有向图,其中有一个子图,这个子图需要满足:图中任意两点 \(v_i\), \(v_j\) (\(v_i\neq v_j\)),有一条路径可以从 \(v_i→v_j\),还有一条路径可以从 \(v_i←v_j\)

强连通分量就是这张图中满足需求且最大的子图。


②:

如何求取强连通分量?

DFS

可能会出现以下四种边:

1.树边:DFS森林中某棵树上的边。

2.后向边:由森林中某棵树上的一个结点指向其祖先结点的点(又被称为返祖边)。

3.前向边:由森林中某棵树上的一个结点指向其后代结点的边(一般来讲删除这种边以后并不会影响结果)。

4.交叉边:是在两个不构成“祖先—后代”关系的结点之间的边(又称横插边)。

接下来引入两个数组:

\(dfn\) 数组以及 \(low\) 数组

\(dfn\) 就是 \(dfs\) 序,\(dfn[i]\) 记录的是顶点 \(i\) 第几个被遍历。

\(low\) 数组表示的是每个点能回到的 \(dfn\) 序最小的结点是哪个。

\(dfn\)\(low\) 数组需要用 \(dfs\) 来求取.

在计算 \(dfn\)\(low\) 的同时,我们也要用栈来存储遍历的点,当某个点 \(dfn[x]==low[x]\) 时,把从这个点到栈顶的点全部取出,这就是一个强连通分量

这就是tarjan算法

代码:

const int maxn=1e4+10;
vector<int> edge[maxn];
int dfn[maxn],low[maxn];
int cnt;
int s[maxn],top;
bool instack[maxn];
int ans,scc[maxn];
void tarjan(int u)
{
    s[++top]=u;//把这个点扔进栈 
    instack[u]=1;	
    dfn[u] =low[u] =++cnt;
    for(int i=0;i<edge[u].size();i++)
	{
        int v=edge[u][i];
        if(!dfn[v])
		{	//如果下一个点没有被搜过,
            tarjan(v);//继续搜
            low[u]=min(low[u],low[v]);//更新low
        }
        else if(instack[v])
		{ //如果下一个点已经被搜过,看他在不在栈里
            low[u]=min(low[u],dfn[v]);//更新low
        }
    }
    if(dfn[u]==low[u])
	{
        ans++;//答案++,第几个强连通分量
        int v;
        while(1)
		{
			v=s[top--];
            scc[v]=ans;	//打标记
            instack[v]=0;//出栈
			if(v==u)
				break;
		}
    }
}

part3:tarjan的其他应用

1.求割边割点

割边定义:在无向连通图 ,若删除边 \(u->v\) 后,原图变成了两个联通分量,则称这条边是⼀条割边

割点定义:在无向连通图 上,若删除节点 \(u\) 和所有与其相连的边的集合 之后,原图变成了两个以上的连通分量,则称节点 \(u\) 是⼀个割点。

2.缩点

将一整个联通分量缩成一个点之后跑拓扑排序

3.点双/边双连通分量

原文地址:http://www.cnblogs.com/Y2y7m/p/16874969.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性