模板:割点、桥与双连通

文章目录

  • 割点
    • 代码
  • 点双连通分量
    • 代码
  • 边双连通分量
    • 代码

割点

和强连通分量十分相似
分为树枝边、前向边和后向边
注意!

if(x!=r&&low[to]>=dfn[x]) cut[x]=1;

这句判断只能在树枝边出现
否则会因为前向边的存在而出错

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
const int N=1e6+100;
struct node{int to,nxt;
}p[2*N];
int fi[N],cnt=-1;
void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt;
}int r;
int dfn[N],t,low[N],cut[N];
void tj(int x){dfn[x]=low[x]=++t;int num=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(!dfn[to]){
//		printf("x=%d to=%d\n",x,to);tj(to);low[x]=min(low[x],low[to]);if(x!=r&&low[to]>=dfn[x]) cut[x]=1;num++;}low[x]=min(low[x],dfn[to]);}if(x==r&&num>1) cut[x]=1;return;
}
int main(){memset(fi,-1,sizeof(fi));scanf("%d%d",&n,&m);int a,b,c;for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);addline(a,b);addline(b,a);	}for(int i=1;i<=n;i++){r=i;if(!dfn[i]) tj(i);}int ans=0;for(int i=1;i<=n;i++){if(cut[i]){ans++;}}printf("%d\n",ans);for(int i=1;i<=n;i++){if(cut[i]){printf("%d ",i);}}return 0;
}

也是类似的tarjan求法
但是需要注意:

  1. 树枝边需要直接跳过
  2. 判断的条件是lowto<dfnxlow_{to}< dfn_xlowto<dfnx(不带等!!)

仔细想想都是有道理的
2.是因为子树如果有连回x的边那么当前边也不是割边
1.是为了2服务的

void tarjan(int x){dfn[x]=low[x]=++tim;for(int i=fi[x];~i;i=p[i].nxt){if(i==(from[x]^1)) continue;int to=p[i].to;//printf("  x=%d to=%d\n",x,to);if(!dfn[to]){from[to]=i;tarjan(to);low[x]=min(low[x],low[to]);if(low[to]>dfn[x]) ans++;}low[x]=min(low[x],dfn[to]);}
}

点双连通分量

定义:点连通度>1的极大子图

考虑建一个栈
把所有的前向边和树枝边压入栈中
每次通过dfnx<=lowtodfn_x<=low_{to}dfnx<=lowto,判断x是隔点时,就把栈里(u,v)(u,v)(u,v)及上面的边全部弹出,他们相连的点组成一个点双连通分量
找分量的好方法:dfs!!

代码

洛谷P3225

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e3+100;
const double eps=1e-6;
inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
int n,m;
int ans;
struct node{int to,nxt,from;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y){//printf("%d->%d w=%d\n",x,y,w);p[++cnt]=(node){y,fi[x],x};fi[x]=cnt;
}
int dfn[N],low[N],zhan[N],tim,top,cut[N],r,tot;
void tarjan(int x){dfn[x]=low[x]=++tim;zhan[++top]=x;int nm=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;//printf("x=%d to=%d\n",x,to);if(!dfn[to]){++nm;tarjan(to);if(low[to]>=dfn[x]){cut[x]=1;}low[x]=min(low[x],low[to]);}else low[x]=min(low[x],dfn[to]);}if(x==r) cut[x]=nm>1;
}
int num,Cut,tag[N],t;
bool vis[N];
void dfs(int x){if(vis[x]||tag[x]==t) return;num++;//printf("x=%d\n",x);if(cut[x]){tag[x]=t;Cut++;return;}vis[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;dfs(to);}
}
int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifint o=0;while(1){memset(fi,-1,sizeof(fi));cnt=-1;memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));tim=0;top=0;memset(cut,0,sizeof(cut));memset(tag,0,sizeof(tag));m=read();n=0;if(!m) return 0;for(int i=1;i<=m;i++){int x=read(),y=read();addline(x,y);addline(y,x);n=max(n,max(x,y));}tot=n;for(int i=1;i<=n;i++){r=i;if(!dfn[i]) tarjan(i);}ll nm=0,ans=1;for(int i=1;i<=n;i++){//printf("i=%d cut=%d\n",i,cut[i]);if(!vis[i]&&!cut[i]){num=0;Cut=0;t=i;dfs(i);printf("i=%d num=%d Cut=%d\n",i,num,Cut);if(Cut==0){nm+=2;ans*=num*(num-1)/2;}else if(Cut==1){nm++;ans*=(num-1);}}}printf("Case %d: %lld %lld\n",++o,nm,ans);}
}

边双连通分量

定义:边连通度>1的极大子图

把桥求出后去掉
剩下的连通块就是边双连通分量
加边使图边双连通的方法:把所有桥连回去,形成一个树。设树度数为1的点的数量为xxx
若x=1,不用加边
否则,加边数为(x+1)/2(x+1)/2(x+1)/2

代码

洛谷P2860

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+100;
const double eps=1e-6;
inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
int n,m;
int ans;
struct node{int to,nxt;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y){//printf("%d->%d w=%d\n",x,y,w);p[++cnt]=(node){y,fi[x]};fi[x]=cnt;
}
int low[N],dfn[N],tim,from[N],cut[N],du[N];
int fa[N];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void merge(int x,int y){x=find(x),y=find(y);fa[x]=y;return;
}
void tarjan(int x){dfn[x]=low[x]=++tim;for(int i=fi[x];~i;i=p[i].nxt){//printf("  x=%d to=%d\n",x,p[i].to);if(i==(from[x]^1)) continue;int to=p[i].to;//printf("  x=%d to=%d\n",x,to);if(!dfn[to]){from[to]=i;tarjan(to);low[x]=min(low[x],low[to]);if(low[to]>dfn[x]){cut[i]=2;cut[i^1]=1;}}low[x]=min(low[x],dfn[to]);}//printf("x=%d dfn=%d low=%d\n",x,dfn[x],low[x]);
}
int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifmemset(fi,-1,sizeof(fi));cnt=1;n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read();addline(x,y);addline(y,x);}for(int i=1;i<=n;i++){if(!dfn[i]) tarjan(i);}for(int i=1;i<=n;i++){fa[i]=i;}for(int x=1;x<=n;x++){for(int i=fi[x];~i;i=p[i].nxt){if(cut[i]) continue;merge(x,p[i].to);}}for(int x=1;x<=n;x++){int xx=find(x);for(int i=fi[x];~i;i=p[i].nxt){if(cut[i]!=2) continue;int yy=find(p[i].to);du[xx]++;du[yy]++;}}for(int i=1;i<=n;i++){if(find(i)==i&&du[i]==1) ans++;}printf("%d\n",ans==1?0:(ans+1)/2);
}
/*
3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
0
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

这两天比较忙&#xff0c;周末也在加班&#xff0c;所以更新的就慢了一点&#xff0c;不过没关系&#xff0c;今天我们就进行千呼万唤的系统开发框架的设计。不知道上篇关于架构设计的文章大家有没有阅读&#xff0c;如果阅读后相信一定对架构设计有了更近一部的理解&#xff0…

喝酒、工作与自律

喝酒 自从开始打算品酒之后&#xff0c;家里的小酒数量不断增加&#xff0c;每天晚上喝个15ml&#xff0c;慢慢也能喝出一些区别了。 酱香、清香、浓香的区别还是挺明显的&#xff0c;闻香就能区别出来 浓香里的五粮液特点很明显&#xff0c;闻的时候有粮香&#xff0c;入口后…

51nod1836-战忽局的手段【期望dp,矩阵乘法】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1836 题目大意 nnn个点mmm次随机选择一个点标记&#xff08;可以重复&#xff09;&#xff0c;求最后被标记点的期望个数。 1≤n,m≤10181\leq n,m\leq 10^{18}1≤n,m≤1018 解题思路 额开始拿方案数推了…

分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0

今年五月的 Build 大会上&#xff0c;微软说 .NET Core 3.0 将带来 WPF / Windows Forms 这些桌面应用的支持。当然&#xff0c;是通过 Windows 兼容包&#xff08;Windows Compatibility Pack&#xff09;实现的。为了提前检查你的程序是否能在未来跑在 .NET Core 3.0 上&…

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) Stone Games

Stone Games 主席树 Code1 #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N1000010; using lllong long; const ll MAX1000000000ll; int n,a[N],m; struct node {int l,r;ll v; }tree[N*40]; int root[N],c…

路径求和(ybtoj-树形dp)

文章目录题目描述解析代码题目描述 给出一棵带边权的树&#xff0c;求所有至少有一个端点为叶节点的所有简单路径的长度和 解析 换一个角度想 考虑将树分割为AB两部分的一条边会存在于多少条符合条件的路径中&#xff08;也就是边权会考虑多少次&#xff09; 不难发现&#…

51nod1675-序列变换【莫比乌斯反演】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1675 题目大意 给出两个长度为nnn的序列a,ba,ba,b&#xff0c;求有多少对x,yx,yx,y满足 gcd(x,y)1且abxbaygcd(x,y)1且a_{b_x}b_{a_y}gcd(x,y)1且abx​​bay​​ 1≤n≤105,1≤ai,bi≤n1\leq n\leq 10^5…

牛客题霸 [子数组最大乘积] C++题解/答案

牛客题霸 [子数组最大乘积] C题解/答案 题目描述 给定一个double类型的数组arr&#xff0c;其中的元素可正可负可0&#xff0c;返回子数组累乘的最大乘积。 题解&#xff1a; 同时记录最大值和最小值&#xff0c;为什么?因为给的元素是存在负数的&#xff0c;当出现负数时…

ML.NET 0.8特性简介

本周.NET生态圈内的更新源源不断&#xff0c;除了.NET Core 2.2&#xff0c;ASP.NET Core 2.2和Entity Framework Core 2.2之外&#xff0c;ML.NET 0.8也一并登上舞台。新的推荐场景ML.NET使用基于矩阵分解(Matrix Factorization)和场感知分解机(Field-aware Factorization Mac…

F-Lucky Pascal Triangle(Lucas+数位dp)

F-Lucky Pascal Triangle issue是fw题解 下面代码TLE了&#xff0c;但是此题数位dp的思想非常值得学习 Lucas的过程相当于把n,mn,mn,m在p进制下的每一位拿出来做组合数 Lucas(n,m,p)∏(nkmk)modp\text{Lucas}(n,m,p)\prod \dbinom {n_k}{m_k} \bmod pLucas(n,m,p)∏(mk​nk​…

树的合并(ybtoj-树上dp)

文章目录题目描述前言解析代码thanks for reading&#xff01;题目描述 前言 全网唯一AC&#xff01;&#xff01;&#xff01; 妙啊 而且还是完全自己想出来的做法 开心 &#xff08;APIO还是没白听&#xff09; 但是思路出来后代码实现十分坎坷 建两个图分别dfs3次那个地方…

牛客题霸 [矩阵元素查找] C++题解/答案

牛客题霸 [矩阵元素查找] C题解/答案 题目描述 已知int一个有序矩阵mat&#xff0c;同时给定矩阵的大小n和m以及需要查找的元素x&#xff0c;且矩阵的行和列都是从小到大有序的。设计查找算法返回所查找元素的二元数组&#xff0c;代表该元素的行号和列号(均从零开始)。保证元…

51nod1821-最优集合【贪心】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1821 题目大意 nnn个可重集合&#xff0c;TTT次询问&#xff0c;询问将集合SxS_xSx​和一个选出大小为kkk的SyS_ySy​的子集合并成的独立集S′SS′满足能够找到一个最大的zzz使得对于任意的正整数i∈[1,z…

.net core中的高效动态内存管理方案

.net core在新增的System.Buffers中引入了一大堆高效内存管理的类&#xff0c;如span和memory、内存池。本文今天这里介绍一个高效动态内存访问方案。ReadOnlySequenceSegment<T>在我们读取数据的过程&#xff0c;很多时候会出现如下场景&#xff1a;不知道数据实际大小一…

C. Sum of Log(数位dp)

C. Sum of Log Code1 暴力记的状态 TLE #include<bits/stdc.h> using namespace std; using lllong long; template <class Tint> T rd() {T res0;T fg1;char chgetchar();while(!isdigit(ch)) {if(ch-) fg-1;chgetchar();}while( isdigit(ch)) res(res<<…

APIO游记(5.19-5.23)

概要 本来以为钱基本是白花了 但惊喜的发现其实没有 APIO之后做了几道题&#xff0c;感觉对题目的分析能力增强了 大概虽然不会任何前置算法&#xff0c;但其中的思路多多少少还是吸收到一些 还有一枚Cu诶 针不戳 课程 5.19决策单调性与四边形不等式 第一天 见识到了天高地…

.net core 上 K8S(三)Yaml文件运行.netcore程序

正文上一章我们通过kubectl run简单运行了一个.netcore网站&#xff0c;但实际的开发中&#xff0c;我们都是通过yaml来实现的。1.编写yaml文件关于yaml文件的格式在此就不多描述了&#xff0c;不熟悉的可以去网上搜一下示例。2.运行yamlkubectl create -f netcore.yaml 我们可…

51nod1676-无向图同构【乱搞】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1676 题目大意 给出两张nnn个点mmm条边的无向图&#xff0c;求这两张图是否同构。 1≤n≤200,1≤m≤4000,1≤T≤201\leq n\leq 200,1\leq m\leq 4000,1\leq T\leq 201≤n≤200,1≤m≤4000,1≤T≤20 解题…

Jozky模板

文章目录字符串处理后缀数组manacherhashKMP最大最小表达法数论约瑟夫环欧拉函数莫比乌斯反演逆序对归并排序求逆序对素数线性筛欧几里得与扩展欧几里得欧几里得算法&#xff1a;扩展欧几里得算法&#xff1a;逆元扩展欧几里得费马小定理欧拉定理递推求逆元__int128高精度运算唯…