有向图的强连通分量

1、Tarjan

/*
Tarjan算法
复杂度O(N+M)
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;const int MAXN=20010;//点数
const int MAXM=50010;//边数
struct Edge{int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况void addedge(int u,int v){edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void Tarjan(int u){int v;Low[u]=DFN[u]=++Index;Stack[top++]=u;Instack[u]=true;for(int i=head[u];i!=-1;i=edge[i].next){v=edge[i].to;if(!DFN[v]){Tarjan(v);if(Low[u]>Low[v])Low[u]=Low[v];}else if(Instack[v]&&Low[u]>DFN[v])Low[u]=DFN[v];}if(Low[u]==DFN[u]){scc++;do{v=Stack[--top];Instack[v]=false;Belong[v]=scc;num[scc]++;}while(v!=u);}
}
void solve(int N){memset(DFN,0,sizeof(DFN));memset(Instack,false,sizeof(Instack));memset(num,0,sizeof(num));Index=scc=top=0;for(int i=1;i<=N;i++)if(!DFN[i])Tarjan(i);
}
void init(){tot=0;memset(head,-1,sizeof(head));
}int main(){return 0;
}

View Code

2、Kosaraju

/*
Kosaraju算法,复杂度O(N+M)
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;const int MAXN=20010;
const int MAXM=50010;
struct Edge{int to,next;
}edge1[MAXM],edge2[MAXM];
//edge1是原图,edge2是逆图GT
int head1[MAXN],head2[MAXN];
bool mark1[MAXN],mark2[MAXN];
int tot1,tot2;
int cnt1,cnt2;
int st[MAXN];//对原图进行dfs,点的结束时间从小到大排序
int Belong[MAXN];//每个点属于哪个连通分量(0~cnt2-1)
int num;//中间变量,用来数某个连通分量中点的个数
int setNum[MAXN];//强连通分量中点的个数,编号0~cnt2-1
void addedge(int u,int v){edge1[tot1].to=v;edge1[tot1].next=head1[u];head1[u]=tot1++;edge2[tot2].to=u;edge2[tot2].next=head2[v];head2[v]=tot2++;
}
void DFS1(int u){mark1[u]=true;for(int i=head1[u];i!=-1;i=edge1[i].next)if(!mark1[edge1[i].to])DFS1(edge1[i].to);st[cnt1++]=u;
}
void DFS2(int u){mark2[u]=true;num++;Belong[u]=cnt2;for(int i=head2[u];i!=-1;i=edge2[i].next)if(!mark2[edge2[i].to])DFS2(edge2[i].to);
}
//点的编号从1开始
void solve(int n){memset(mark1,false,sizeof(mark1));memset(mark2,false,sizeof(mark2));cnt1=cnt2=0;for(int i=1;i<=n;i++)if(!mark1[i])DFS1(i);for(int i=cnt1-1;i>=0;i--)if(!mark2[st[i]]){num=0;DFS2(st[i]);setNum[cnt2++]=num;}
}int main(){return 0;
}

View Code

割点与桥

UVA 796 Critical Links

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
/*
*  求 无向图的割点和桥
*  可以找出割点和桥,求删掉每个点后增加的连通块。
*  需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重
*/
const int MAXN = 10010;
const int MAXM = 100010;
struct Edge
{int to,next;bool cut;//是否为桥的标记
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN];
int Index,top;
bool Instack[MAXN];
bool cut[MAXN];
int add_block[MAXN];//删除一个点后增加的连通块
int bridge;void addedge(int u,int v)
{edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut = false;head[u] = tot++;
}void Tarjan(int u,int pre)
{int v;Low[u] = DFN[u] = ++Index;Stack[top++] = u;Instack[u] = true;int son = 0;for(int i = head[u];i != -1;i = edge[i].next){v = edge[i].to;if(v == pre)continue;if( !DFN[v] ){son++;Tarjan(v,u);if(Low[u] > Low[v])Low[u] = Low[v];//桥//一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。if(Low[v] > DFN[u]){bridge++;edge[i].cut = true;edge[i^1].cut = true;}//割点//一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。//(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,//即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)if(u != pre && Low[v] >= DFN[u])//不是树根
            {cut[u] = true;add_block[u]++;}}else if( Low[u] > DFN[v])Low[u] = DFN[v];}//树根,分支数大于1if(u == pre && son > 1)cut[u] = true;if(u == pre)add_block[u] = son - 1;Instack[u] = false;top--;
}void solve(int N)
{memset(DFN,0,sizeof(DFN));memset(Instack,false,sizeof(Instack));memset(add_block,0,sizeof(add_block));memset(cut,false,sizeof(cut));Index = top = 0;bridge = 0;for(int i = 1;i <= N;i++)if( !DFN[i] )Tarjan(i,i);printf("%d critical links\n",bridge);vector<pair<int,int> >ans;for(int u = 1;u <= N;u++)for(int i = head[u];i != -1;i = edge[i].next)if(edge[i].cut && edge[i].to > u){ans.push_back(make_pair(u,edge[i].to));}sort(ans.begin(),ans.end());//按顺序输出桥for(int i = 0;i < ans.size();i++)printf("%d - %d\n",ans[i].first-1,ans[i].second-1);printf("\n");
}
void init()
{tot = 0;memset(head,-1,sizeof(head));
}
//处理重边
map<int,int>mapit;
inline bool isHash(int u,int v)
{if(mapit[u*MAXN+v])return true;if(mapit[v*MAXN+u])return true;mapit[u*MAXN+v] = mapit[v*MAXN+u] = 1;return false;
}
int main()
{int n;while(scanf("%d",&n) == 1){init();int u;int k;int v;//mapit.clear();for(int i = 1;i <= n;i++){scanf("%d (%d)",&u,&k);u++;//这样加边,要保证正边和反边是相邻的,建无向图while(k--){scanf("%d",&v);v++;if(v <= u)continue;//if(isHash(u,v))continue;
                addedge(u,v);addedge(v,u);}}solve(n);}return 0;
}

View Code

转载于:https://www.cnblogs.com/bofengyu/p/5003327.html

有向图的强连通分量,割点与桥相关推荐

  1. 算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 第一问:通过tarjan算法求出强连通分量并且缩点后,统计入度为0的点的个数p即可. 第二问,至少加几条边才能使图变成强连通分量?这 ...

  2. 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 强连通图:给定一张有向图.若对于图中任意两个结点x,y,既存在从x到y的路径,也存在从y到x的路径,则称该有向图是"强连通 ...

  3. C++Kosaraju找有向图的强连通分量算法(附完整源码)

    C++Kosaraju找有向图的强连通分量算法 C++Kosaraju找有向图的强连通分量算法完整源码(定义,实现,main函数测试) C++Kosaraju找有向图的强连通分量算法完整源码(定义,实 ...

  4. 缩点(有向图的强连通分量)学习笔记

    缩点(有向图的强连通分量)学习笔记 1.什么是强连通分量?: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路 ...

  5. 有向图的强连通分量(SCC)

    有向图的强连通分量(SCC) 1. 有向图的强连通分量原理 原理 强连通分量是针对有向图来说的.如下的讲解默认都是针对有向图的. 连通分量:对于一个有向图中的一些点来说,如果任意两点都能相互到达,则称 ...

  6. 求无向图的连通分量或有向图的强连通分量—tarjan()ccf高速公路

    概念定义: 在图论中,连通图基于连通的概念. 1. 连通(无向图): 若顶点Vi能通过路径到达Vj,那么称为Vi和Vj是连通的 对无向图:若从顶点Vi到顶点Vj有路径相连(当然从j到i也一定有路径), ...

  7. 有向图的强连通分量算法

    有向图的强连通分量算法 强连通分量定义 在有向图中,某个子集中的顶点可以直接或者间接互相可达,那么这个子集就是此有向图的一个强连通分量,值得注意的是,一旦某个节点划分为特定的强连通分量后,此顶点不能在 ...

  8. 使用并查集实现查找无向图的连通分量和求解有向图的强连通分量

    目录 1.无向图的连通分量 2.求解连通分量算法的实现 3.有向图的强连通分量 4.求解有向图的强连通分量 使用C语言实现并查集 有向图和无向图 1.无向图的连通分量 无向图G中,如果存在从顶点v1到 ...

  9. 【图论】—— 有向图的强连通分量

    给定有向图 ,若存在 ,满足从 出发能到达 中所有的点,则称 是一个"流图"( Flow Graph ),记为  ,其中, 称为流图的源点. 在一个流图  上从  进行深度优先遍历 ...

最新文章

  1. BP算法双向传_链式求导最缠绵(深度学习入门系列之八)
  2. centos7 源码编译安装mysql 5.7.21
  3. 华为云客户端_效果图云渲染已成趋势,云渲染如何选择?
  4. SwiftUI之深入解析高级动画的几何效果GeometryEffect
  5. 分布式是写出来的(一)
  6. 2016-08-31
  7. 网站导航颜色停留_提高网站流量的方法有哪些?
  8. windows定时自动运行R脚本的正确姿势
  9. 实现IP地址归属地显示功能、号码归属地查询
  10. 仿高德地图点亮城市html,高德地图怎么点亮城市_高德地图点亮城市教程_3DM手游...
  11. OpenCV特征检测与匹配方法概览
  12. Android中使用Toast弹出信息提示时的用户体验优化
  13. 计算机网络连接黄感叹号,电脑连接路由器网络连接显示黄色感叹号的解决办法...
  14. 微众银行AI团队领衔推动人工智能国际标准的制定
  15. 【hbase问题】org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not run
  16. Android String字符串截取方法总结
  17. JVM线程本地分配缓冲区(Thread Local Allocation Buffer)TLAB详解
  18. 软件开发部门经理岗位职责
  19. 谷歌二次验证 Google Authenticator
  20. 共勉。怎么摆脱习惯性刷手机的习惯?

热门文章

  1. [Aaronyang] 写给自己的WPF4.5 笔记17[Page实现页面导航]
  2. 三层BP神经网络的python实现
  3. ERROR 1372 (HY000): Password hash should be a 41-digit hexadecimal number;
  4. 【原】行内元素产生水平空隙是bug吗
  5. 标题: ZZ- Linux 系统裁减指南(LiPS)
  6. python 自动复制分类_leetcode python 常见分类问题模板(复制粘贴就能用) 更新中......
  7. python frombuffer_numpy.getbuffer和numpy.frombu
  8. 线上redis一般安在linux_Redis企业级应用-Linux安装搭建一个完整的linxu线上服务(上)...
  9. Mysql主从复制集群类型和搭建方法
  10. 怎么恢复linux定时器任务,定时操作 crontab at 以及恢复定时操作