分享
分享赚钱 收藏 举报 版权申诉 / 39

类型强连通分量.pptx

  • 上传人:kpmy5893
  • 文档编号:6921511
  • 上传时间:2019-04-27
  • 格式:PPTX
  • 页数:39
  • 大小:194.98KB
  • 配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    强连通分量.pptx
    资源描述:

    1、北京大学信息学院 郭炜,本讲义部分内容参考http:/ 以及北京大学信息学院实验班袁洋、陈科吉同学讲义,还有其他一些网站恕不一一列出,特此致谢,强连通分支、桥和割点,定 义,在有向图G中,如果任意两个不同的顶点相互可达,则称该有向图是强连通的。有向图G的极大强连通子图称为G的强连通分支。,转置图的定义:将有向图G中的每一条边反向形成的图称为G的转置GT。(注意到原图和GT的强连通分支是一样的),Korasaju算法求有向图强连通分支,procedure Strongly_Connected_Components(G);begin1.深度优先遍历G,算出每个结点u的结束时间fu,起点如何选择无所

    2、谓。 2.深度优先遍历G的转置图GT,选择遍历的起点时,按照结点的结束时间从大到小进行。遍历的过程中,一边遍历,一边给结点做分类标记,每找到一个新的起点,分类标记值就加1。3. 第2步中产生的标记值相同的结点构成深度优先森林中的一棵树,也即一个强连通分量end; 证明参考:http:/ 枝;(b)G的转置图GT 依次以b,c,g,h为起点做DFS, 得到4个强连通分量,算法复杂度分析,深度优先搜索的复杂度:(V + E) 计算GT的复杂度:0或者(V + E)(临接表) 所以总的复杂度为:(V + E) 非常好的算法!,POJ2186:Popular Cows,给定一个有向图,求有多少个顶点是

    3、由任何顶点出发都可达的。顶点数= 10,000,边数 = 50,000,有向无环图中唯一出度为0的点,一定可以由任何点出发均可达(由于无环,所以从任何点出发往前走,必然终止于一个出度为0的点),有用的定理:,POJ2186: 解题思路,1. 求出所有强连通分量2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。3. DAG上面如果有唯一的出度为0的点,则该点能被所有的点可达。那么该点所代表的连通分量上的所有的原图中的点,都能被原图中的所有点可达,则该连通分量的点数,就是答案。4. DAG上面如果有不止一个出度为0的点,则这些点互相不可达,原问题无解,答案为0,POJ2186: 解题思路,

    4、缩点的时候不一定要构造新图,只要把不同强连通分量的点染不同颜色,然后考察各种颜色的点有没有连到别的颜色的边即可(即其对应的缩点后的DAG图上的点是否有出边)。,POJ1236: Network of Schools,题目大意:N(2N100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。,ACM1236: Network of Schools,给定一个有向图,求:1)

    5、 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点顶点数= 100,有向无环图中所有入度不为0的点,一定可以由某个入度为0的点出发可达。(由于无环,所以从任何入度不为0的点往回走,必然终止于一个入度为0的点),有用的定理:,ACM1236: 解题思路,1. 求出所有强连通分量2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少,ACM1236: 解题思路,在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少加边的方法:要为每个入度为0

    6、的点添加入边,为每个出度为0的点添加出边假定有 n 个入度为0的点,m个出度为0的点,max(m,n)就是第二个问题的解(证明难,略),思想:做一遍DFS,用dfni表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用lowi表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间。初始时dfni=lowi在DFS过程中会形成一搜索树。在搜索树上越先遍历到的节点,显然dfn的值就越小。DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈。如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfnv(

    7、更新为lowv也可以)。,有向图强连通分支的Tarjan算法,如果一个节点u已经DFS访问结束,而且此时其low值等于dfn值,则说明u可达的所有节点,都不能到达任何在u之前被DFS访问的节点 - 那么该节点u就是一个强连通分量在DFS搜索树中的根。此时将栈中所有节点弹出,包括u,就找到了一个强连通分量,有向图强连通分支的Tarjan算法,有向图强连通分支的Tarjan算法,void Tarjan(u) dfnu=lowu=+indexstack.push(u)for each (u, v) in E if (v is not visted) tarjan(v) lowu = min(lowu

    8、, lowv) else if (v in stack) lowu = min(lowu, dfnv) if (dfnu = lowu) /u是一个强连通分量的根repeat v = stack.pop print v until (u= v) /退栈,把整个强连通分量都弹出来 /复杂度是O(E+V)的,无向连通图求割点和桥,无向连通图中,如果删除某点后,图变成不连通,则称该点为割点。无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。,求桥和割点的Tarjan算法,思路和有向图求强连通分量类似在深度优先遍历整个图过程中形成的一棵搜索树一个顶点u是割点,当且仅当满足(1)或(2) (1)

    9、 u为树根,且u有多于一个子树。 (2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得dfn(u)=low(v)。一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足dfn(u)low(v)(前提是其没有重边)。,lowu定义为u或者u的子树中能够通过非父子边追溯到的最早的节点的DFS开始时间 如果下面程序没有: if(v 不是u 的父节点) 则求不出桥了,求桥和割点的Tarjan算法,求桥和割点和桥的Tarjan算法,Tarjan(u) du=lowu=+indexfor each (u, v) in E if (v is not viste

    10、d) tarjan(v) lowu = min(lowu, lowv)du u 有至少两个子节点else u 是割点 u 有一个子节点v,满足du= lowv ,Tarjans algorithm,也可以先用Tajan()进行dfs算出所有点的low和dfn值,并记录dfs过程中每个点的父节点,然后再把所有点看一遍,看其low和dfn,以找出割点和桥。找桥的时候,要注意看有没有重边。有重边,则不是桥。,无重边连通无向图求割点和桥的程序 给出点数和所有的边,求割点和桥Input: (11点13边)11 13 1 2 1 4 1 5 1 6 2 11 2 3 4 3 4 9 5 8 5 7 6 7

    11、 7 10 11 3,output: 1 4 5 7 5,8 4,9 7,10,/无重边连通无向图求割点和桥的程序 #include #include using namespace std;#define MyMax 200 typedef vector Edge; vector G(MyMax); bool VisitedMyMax ; int dfnMyMax ; int lowMyMax ; int FatherMyMax; /DFS树中每个点的父节点 bool bIsCutVetextMyMax; /每个点是不是割点 int nTime; /Dfs时间戳 int n,m; /n是点数

    12、,m是边数,void Tarjan(int u, int father) /father 是u的父节点 Fatheru = father;int i,j,k;lowu = dfnu = nTime +;for( i = 0;i Gu.size() ;i + ) int v = Gui;if( ! dfnv) Tarjan(v,u);lowu = min(lowu,lowv);else if( father != v ) /连到父节点的回边不考虑,否则求不出桥lowu = min(lowu,dfnv); ,void Count() /计算割点和桥int nRootSons = 0; int i;

    13、Tarjan(1,0);for( i = 2;i 1)bIsCutVetext1 = true;for( i = 1;i 0 ,int main() int u,v;int i;nTime = 1;cin n m ; /n是点数,m是边数for( i = 1;i u v; /点编号从开始Gv.push_back(u);Gu.push_back(v);memset( dfn,0,sizeof(dfn);memset( Father,0,sizeof(Father);memset( bIsCutVetext,0,sizeof(bIsCutVetext);Count();return 0; ,求无向

    14、图连通图点双连通分支(不包含割点的极大连通子图):,对于点双连通分支,实际上在求割点的过程中就能顺便把每个点双连通分支求出。建立一个栈,存储当前双连通分支,在搜索图时,每找到一条树枝边或反向边,就把这条边加入栈中。如果遇到某时满足dfn(u)=low(v),说明u是一个割点,同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,组成一个点双连通分支。割点可以属于多个点双连通分支,其余点和每条边只属于且属于一个点双连通分支。,求无向连通图点双连通分量(没有割点的连通分量),假定没有重边,Input: (11点13边)11 13 1 2 1 4 1 5 1 6 2 11 2

    15、3 4 3 4 9 5 8 5 7 6 7 7 10 11 3,output:Block No: 1 4,9 Block No: 2 4,1 3,4 3,2 11,3 2,11 1,2 Block No: 3 5,8 Block No: 4 7,10 Block No: 5 6,1 7,6 5,7 1,5,/求无向连通图点双连通分量(没有割点的连通分量),假定没有重边 #include #include #include using namespace std; #define MyMax 200 typedef vector Edge; vector G(MyMax); int dfnMyM

    16、ax ; int lowMyMax ; int nTime; int n,m; /n是点数,m是边数 struct Edge2 int u;int v;Edge2(int u_,int v_):u(u_),v(v_) ; deque Edges; int nBlockNo = 0;,void Tarjan(int u, int father) int i,j,k;lowu = dfnu = nTime +;for( i = 0;i Gu.size() ;i + ) int v = Gui;if( ! dfnv) /v没有访问过/树边要入栈Edges.push_back(Edge2(u,v);T

    17、arjan(v,u);lowu = min(lowu,lowv);Edge2 tmp(0,0);if(dfnu = lowv) /从一条边往下走,走完后发现自己是割点,则栈中的边一定全是和自己在一个双连通分量里面/根节点总是和其下的某些点在同一个双连通分量里面cout “Block No: “ + nBlockNo endl;,do tmp = Edges.back();Edges.pop_back ();cout dfnv)/子孙连接到祖先的回边要入栈,但是子孙连接到自己的边,此处肯定已经入过栈了,不能再入栈Edges.push_back(Edge2(u,v); /对应 for( i = 0

    18、;i Gu.size() ;i + ) ,int main() int u,v;int i;nTime = 1;cin n m ; /n是点数,m是边数nBlockNo = 0;for( i = 1;i u v; /点编号从1开始Gv.push_back(u);Gu.push_back(v);memset( dfn,0,sizeof(dfn);Tarjan(1,0);return 0; ,求无向连通图边双连通分支(不包含桥的极大连通子图):,只需在求出所有的桥以后,把桥边删除,原图变成了多个连通块,则每个连通块就是一个边双连通分支。桥不属于任何一个边双连通分支,其余的边和每个顶点都属于且只属于

    19、一个边双连通分支。,POJ 3352 Road Construction,给你一个图,要求你加入最少的边,使得最后得到的图为一个边双连通分支。所谓的边双连通分支,即不存在桥的连通分支。可以求出所有的桥,把桥删掉。然后把所有的连通分支求出来,显然这些连通分支就是原图中的双连通分支。把它们缩成点,然后添上刚才删去的桥,就构成了一棵树。在树上添边使得树变成一个双连通分支即可。,POJ 3352 Road Construction,本题只要求输出一共需要添加多少条边,而不需要求具体的方案。其实可以统计度为1的叶子节点(设共有x个),然后直接输出(x+1)/2即可,命题:一棵有n(n=2)个叶子结点的树

    20、,至少须添加ceil(n/2)条边,就能转变为一个没有桥的图。或者说,使得图中每条边,都至少在一个环上。证明:这里只证明n为偶数的情况。n为奇数的证明类似。先证明添加n/2条边一定可以达成目标。n=2时,显然只需将这两个叶子间连一条边即可。命题成立。 设n=2k(k=1)时命题成立,即S2k=k。下面将推出n=2(k+1)时命题亦成立。n=2k+2时,选取树中最长的迹,设其端点为a,b;并设离a最近的度=3的点为a,同理设b。 (关于a和b的存在性问题:由于a和b的度都为1,因此树中其它的树枝必然从迹之间的某些点引出。否则整棵树就是迹,n=22k+2,不可能。),在a,b间添一条边,则迹上的所

    21、有边都已不再是桥。这时,将刚才添加的边,以及aa之间,bb之间的边都删去,得到一棵新的树。因为删去的那些边都已经符合条件了,所以在之后的构造中不需要考虑它们。由于之前a和b的度=3,所以删除操作不会使他们变成叶子。因此新的树必然比原树少了两个叶子a,b,共有2k个叶子。由归纳知需要再加k条边。因此对n=2k+2的树,一共要添加k+1条边。(最长的迹保证a,b不相同) 因此证得n/2可取。再证明n/2是最小的解。显然,只有一个叶子结点被新加的边覆盖到,才有可能使与它相接的那条边进入一个环中。而一次加边至多覆盖2个叶子。因此n个叶子至少要加n/2条边。 证毕。,其他题目,acm1236,acm3180,acm2762(强连通+拓扑排序),acm2553, acm3114(强连通+dijkstra), acm3160(强连通+DP),

    展开阅读全文
    提示  道客多多所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:强连通分量.pptx
    链接地址:https://www.docduoduo.com/p-6921511.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    道客多多用户QQ群:832276834  微博官方号:道客多多官方   知乎号:道客多多

    Copyright© 2025 道客多多 docduoduo.com 网站版权所有世界地图

    经营许可证编号:粤ICP备2021046453号    营业执照商标

    1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10.png



    收起
    展开