连通分量

图论500题

岁酱吖の 提交于 2019-12-05 12:08:38
【HDU】 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 1233 还是畅通工程 基础最小生成树★ 1863 畅通工程 基础最小生成树★ 1875 畅通工程再续 基础最小生成树★ 1879 继续畅通工程 基础最小生成树★ 3371 Connect the Cities 简单最小生成树★ 1301 Jungle Roads 基础最小生成树★ 1162 Eddy's picture 基础最小生成树★ 1198 Farm Irrigation 基础最小生成树★ 1598 find the most comfortable road 枚举+最小生成树★★ 1811 Rank of Tetris 并查集+拓扑排序★★ 3926 Hand in Hand 同构图★ 3938 Portal 离线+并查集★★ 2489 Minimal Ratio Tree dfs枚举组合情况+最小生成树★ 4081 Qin Shi Huang's National Road System 最小生成树+DFS★★??? 4126 Genghis

LuoguP4306连通数 Tarjan

只谈情不闲聊 提交于 2019-12-04 04:11:00
https://www.luogu.org/problem/P4306 https://www.lydsy.com/JudgeOnline/problem.php?id=2208 这道题里面还有缩点+拓扑排序 话不多说直接上代码,代码里有详细解释,看不懂的先去看看搜索树方面的知识,lyd书上有 #include <bits/stdc++.h> using namespace std; int n, ans, cnt, sum, tot;//tot记录图中有几个强连通分量 bool v[2021];//判断节点是否被访问过 int dfn[2021];//节点i搜索的次序编号(时间戳)每个点第一次被访问的时间顺序 int low[2021];//表示u或u的子树能够追溯到的最早的栈中节点的次序号,时间戳的最小值 int scc[2021];//表示 x 所在的强连通分量的编号 int deg[2021];//储存强连通分量的入度 int head[2021];//一开始的图 int head2[2021];//保存缩点后新的有向无环图 int stk[2021], top;//数组模拟栈,top记录栈中元素个数 int sze[2021];//记录每个强连通分量中元素个数 bitset<150021> f[100021]; queue<int> q; struct edge{ int

Tarjan专题

烂漫一生 提交于 2019-12-03 15:19:59
Tarjan专题 由于时间关系,本文只针对Tarjan做总结。如果有对Tarjan的入门有疑问请自行百度 有向图tarjan 在有向图中跑tarjan,通常都是求强连通分量(其中的所有点都可以间接直接到达)。一个点也算强连通。 设当前的节点为 \(u\) ,它的儿子节点为 \(v\) ,如果 \(v\) 没有被访问,那么时间戳戳一个, low[u]=min(low[u],low[v]) 。如果被访问过,那么 low[u]=min(low[u],dfn[v]) 。这里必须用一个栈来保存强连通及其大小。当一个点访问玩所有的儿子后,还有 dfn[u]==low[u] ,那么在这个栈里面的元素就都是强连通分量。因为我们dfs是是以树枝边进行遍历的。如果 \(u\) 能到达的最早的节点都只有它自己,那么它的儿子更没有机会遍历到前面的节点。输出强连通只需输出栈内元素即可。 缩点 求了强连通之后,将强连通变成一个点,那么整张图就变成了有向无环图。我们就可以在上面做一些拓扑序之类的问题了。 无向图tarjan 无向图有一些改变。边从有向变成了无向,任意两点只要连边就可以到达。所以在无向图上求强连通是没有意义的。 在无向图上一般求割点与桥。 顾名思义,干掉割点,其他的点就无法全部连通,干掉桥,其他的点也无法全部连通。见图: 对于割点,我们可以发现:存在 dfn[u]<=low[v] 。如果不存在

tarjan复习笔记

最后都变了- 提交于 2019-12-03 09:28:16
tarjan复习笔记 (关于 tarjan 读法, 优雅一点读塔洋,接地气一点读塔尖 ) 0. 连通分量 有向图: 强连通分量(SCC)是个啥 就是一张图里面两个点能互相达到,那么这两个点在同一个强连通分量里, 极大强连通分量 就是最大的强连通分量。 无向图: 一个全部联通的子图就是一个连通分量。 其中用到tarjan暂时还有 边双连通分量 (e-DCC)和 点双连通分量 (v-DCC) 边双连通分量(e-DCC) 指的是一个子图中没有桥的话,这就是一个边双连通分量。 一个无向图的每一个极大边双连通子图称作此无向图的双连通分量。 点双连通分量(v-DCC) 对于一个无向图,如果一个点集,它内部的任意一个点对之间,至少有两条点完全不重复的路径,那么这个点集就是原图的一个点双连通分量。 无向图的双连通分量下面 待会复习 tarjan求强连通分量 这个就是所谓的tarjan强连通分量——缩点了。 对于一个单向联通的子图,我们从一个点出发会得到一个 搜索树 , 但是这个子图可不仅仅只有搜索树上的边。 (搜索树上的边下简称树边,非搜索树上的但是遇到的边下简称非树边) 按照搜索的顺序把点压到一个栈里。 如果当前我们找到一个非树边然后指向之前栈中的点里,那么从那个点到这个点之间都是强连通分量的一部分。 但是我们怎么找到一个最大的强连通分量呢? 我们设置一个搜索顺序 dfn[] 和追溯值 low[

边双连通分量 jarjan (poj 3177)

不问归期 提交于 2019-12-02 16:43:05
大意:给定一个无向连通图,判断至少加多少的边,才能使任意两点之间至少有两条的独立的路(没有公共的边,但可以经过同一个中间的顶点)。 思路:在同一个双连通分量里的所有的点可以看做一个点,收缩后,新图是一棵树,树的边便是原图的桥。现在问题转化为“在树中至少添加多少条边能使图变成边双连通图”,即添加的边的个数=(树中度为一的节点数目+1)/2,用trajan算法求双联通分量 这是一个模板 1 #include<iostream> 2 #include<cstdio> 3 #include<string.h> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 using namespace std; 8 const int maxn=1e4+10; 9 struct node 10 { 11 int v,cut,nxt; 12 }G[2*maxn]; 13 int cnt; 14 int head[maxn]; 15 int Stack[maxn]; 16 int instack[maxn]; 17 int low[maxn],dfn[maxn]; 18 int belong[maxn],du[maxn]; 19 int block,index; 20 int bridge,top; 21 void init() 22

吖是“并查集”

泪湿孤枕 提交于 2019-12-02 04:53:43
今天遇到PAT1021,题目中要判断一个图的连通分量数目,一开始想着用 “二维数组存储边的信息+DFS遍历” 来做,后来发现其他题解都用一个叫 “并查集” 的东西来解决分组的问题。 啥是 “并查集” 并查集用来干啥 并查集是用来解决图论中分类问题的一种树形数据结构,常用的就是解决我目前遇到的连通分量的判断问题。 并查集长啥样 并查集就是一个森林,森林里面有很多棵树,我们通过并查集的 “find”(查找) 和 “merge”(合并) 算法来判断将森林里面的树分类。 来源: https://www.cnblogs.com/chuan-chuan/p/11730672.html

最大半连通子图

南笙酒味 提交于 2019-12-02 03:16:19
https://loj.ac/problem/10092 题目描述   给出一张图,定义图的半连通子图为点集S中任意两点u、v都存在一条u到v的简单路径或v到u的简单路径,求这张图的最大半连通子图的节点数和个数。 思路   首先显然一个强连通子图一定是半连通子图,所以我们可以先进行缩点,这样并不影响结果的判定。接下来考虑缩点后的DAG,最大半连通子图可以转化为DAG上最长链的长度,对于这个我们可以用类似最短路方法,不过由于是DAG我们可以直接进行拓扑排序时更新最短路的值,接下来再类似最短路计数用sum[i]记录到i的路径个数。   不过需要注意虽然原图中保证五重边,但缩点可能两个强连通分量间有多个有向边相连接,由于半连通子图时点集,与边无关,这会影响到最大半连通子图的计数,所以要去重。 代码 #include <bits/stdc++.h> using namespace std; const int N=1e5+10,M=1e6+10; struct Edge { int x,y; }e[M]; bool cmp(Edge a,Edge b) { if(a.x!=b.x)return a.x<b.x; else return a.y<b.y; } int head[N],nxt[M],to[M],tot; int n,m; void add_edge(int x,int y) {

tarjan好题

坚强是说给别人听的谎言 提交于 2019-12-01 08:56:29
CF652E 洛谷上的 这道题 草从早上调到晚上,最后由帅气的gigo_64同学 调出了我那个无比蒟蒻的垃圾渣渣nmsl草我无语了fuck idiot的问题 首先来分析这道题的做法 当我们看到这种类型的题 我们首先是不会想到边双连通分量的 所以只能多做 然后就熟练了 (说了和没说一样) 但是可以记住的是 边双联通分量可以解决的是缩点之快速求必经边,必经点之类的问题 在这道题中我们可以用边双连通分量缩点,缩完点之后就会是一棵树,然后直接从起点dfs到终点为止 我们可以在处理边双连通分量的时候就处理在该边双连通分量中是否包含魔法石 然后dfs的时候判断经过的边双连通分量或者是边是否包含魔法石 包含输出1 否则输出0 需要注意的一点是,多组数据在clear的时候 如果first数组赋值为-1 需要在遍历的时候 for(int i=first[x];i!=-1;i=nxt[i]) f o r ( i n t i = f i r s t [ x ] ; i ! = − 1 ; i = n x t [ i ] ) emmm 我tm就是因为之前不知道-1是true的 然后判定条件只打了i 然后就凉凉 关键是凉凉成40分?错的数据贼大完全调试不出来 再次感谢gigo_64!! #include <iostream> #include <algorithm> #include <cstring> /

bzoj 2208 //2208: [Jsoi2010]连通数

大憨熊 提交于 2019-11-29 23:44:36
bzoj 2208 //2208: [Jsoi2010]连通数 //在线测评地址 https://www.lydsy.com/JudgeOnline/problem.php?id=2208 更多题解,详见 https://blog.csdn.net/mrcrack/article/details/90228694 BZOJ刷题记录 //2208: [Jsoi2010]连通数 //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=2208 //第一个思路,Floyd算法,求最短路径,算法的时间复杂度O(n^3),看了数据范围 N不超过2000,只好作罢 //统计 连通数 时,采用O(n^2)算法即可 //问题是,如何确认2点连通,这个算法的时间复杂度,如何降下来。 //多点的连通问题。 //强连通分量及缩点tarjan算法解析https://blog.csdn.net/acmmmm/article/details/16361033可看此文,手绘图。 //初探tarjan算法(求强连通分量) https://www.luogu.org/blog/styx-ferryman/chu-tan-tarjan-suan-fa-qiu-qiang-lian-tong-fen-liang-post 此文值得一看 /

【2019.9.17】Za

本小妞迷上赌 提交于 2019-11-29 22:15:56
Za yyb Fibonacci的性质 \(gcd(f[i],f[i+1])=1\) 证明 \(gcd(f[i],f[i+1])\) \(=gcd(f[i+1]-f[i],f[i])\) \(=gcd(f[i-1],f[i])\) \(=....\) \(=gcd(f[1],f[2])=1)\) \(f[m+n]=f[m−1]f[n]+f[m]f[n+1]f[m+n]=f[m−1]f[n]+f[m]f[n+1]\) \(gcd(f[n+m],f[n])=gcd(f[n],f[m])gcd(f[n+m],f[n])=gcd(f[n],f[m])\) 由上面式子得到 \(gcd(f[n+m]=f[m−1]f[n]+f[m]f[n+1],f[n])gcd(f[n+m]=f[m−1]f[n]+f[m]f[n+1],f[n])\) \(=gcd(f[n+1]f[m],f[n])=gcd(f[n+1]f[m],f[n])\) \(=gcd(f[n+1],f[n])∗gcd(f[m],f[n])=gcd(f[n+1],f[n])∗gcd(f[m],f[n])\) \(=1∗gcd(f[m],f[n])=1∗gcd(f[m],f[n])\) \(=gcd(f[m],f[n])\) \(gcd(f[n],f[n+m])=f[gcd(n,n+m)]gcd(f[n],f[n+m])=f[gcd(n,n