无向图的双连通块(点的双连通)&&边的双连通算法
2015-07-23 21:51
429 查看
无向图的双连通块
题目描述
给出一个无向图,求其中双连通块的个数以及其中最大的双连通块。
输入
第1行:2个整数n和m,n表示图的结点个数,m表示图中边的数量 (1<=n<=100000, 1<=m<=1000000)
接下来m行,每行2个整数,表示一条边
输出
第1行:1个整数,表示整个图中双连通块的数量
第2行:1个整数,表示整个图中最大的双连通块的边的条数
接下来依次输出最大的双连通块的各条边,按字典序输出,即按边的端点编号从小到大输出,每条边先输出编号小的端点,再输出编号大的端点
若有多个边数相同的最大双连通块,输出字典序最小的一个
样例输入
9 10
1 2
4 1
2 3
4 2
1 5
5 6
6 7
6 8
7 9
8 7
样例输出
6
3
1 2
1 4
2 4
把割点切开就好了..
边的双连通即为删去割边后的连通块
**点双连通即为没有割点的块,边亦如是
题目描述
给出一个无向图,求其中双连通块的个数以及其中最大的双连通块。
输入
第1行:2个整数n和m,n表示图的结点个数,m表示图中边的数量 (1<=n<=100000, 1<=m<=1000000)
接下来m行,每行2个整数,表示一条边
输出
第1行:1个整数,表示整个图中双连通块的数量
第2行:1个整数,表示整个图中最大的双连通块的边的条数
接下来依次输出最大的双连通块的各条边,按字典序输出,即按边的端点编号从小到大输出,每条边先输出编号小的端点,再输出编号大的端点
若有多个边数相同的最大双连通块,输出字典序最小的一个
样例输入
9 10
1 2
4 1
2 3
4 2
1 5
5 6
6 7
6 8
7 9
8 7
样例输出
6
3
1 2
1 4
2 4
把割点切开就好了..
#include<cstdio> #include<stack> #include<iostream> #include<vector> #include<algorithm> #include<cstring> using namespace std; #define MAXN 100000 #define MAXM 1000000 struct node{ int v; node *next; }edge[MAXM*2+10],*adj[MAXN+10],*ecnt=&edge[0]; int n,m,dfn[MAXN+10],low[MAXN+10],dcnt,block; int ccnt,acnt; stack<pair<int , int> > e; struct list{ pair<int , int> p; }ans[MAXM+10],cmp[MAXM+10]; void addedge(int u,int v) { node *p=++ecnt; p->v=v; p->next=adj[u]; adj[u]=p; } void read() { int x,y; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } } bool compare(list x,list y) { if(x.p.first==y.p.first) return x.p.second<y.p.second; return x.p.first<y.p.first; } void cut_block(int u,int v) { ccnt=0; pair<int , int> tmp; do{ tmp=e.top(); e.pop(); cmp[++ccnt].p=tmp; }while(!(tmp.first==u&&tmp.second==v)); for(int i=1;i<=ccnt;i++) if(cmp[i].p.first>cmp[i].p.second) swap(cmp[i].p.first,cmp[i].p.second); sort(cmp+1,cmp+ccnt+1,compare); bool flag=false; if(ccnt>acnt) flag=true; else if(ccnt==acnt){ for(int i=1;i<=ccnt;){ if(cmp[i].p.first>ans[i].p.first) break; else if(cmp[i].p.first<ans[i].p.first) flag=true; else if(cmp[i].p.second<ans[i].p.second) flag=true; else if(cmp[i].p.second>ans[i].p.second) break; else i++; if(flag) break; } } if(flag){ acnt=ccnt; memcpy(ans,cmp,sizeof(cmp)); } } void dfs(int u,int fa) { dfn[u]=low[u]=++dcnt; for(node *p=adj[u];p;p=p->next){ int v=p->v; if(!dfn[v]){ e.push(make_pair(u,v)); dfs(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ cut_block(u,v); block++; } } else if(v!=fa&&dfn[u]>dfn[v]){ low[u]=min(low[u],dfn[v]); e.push(make_pair(u,v)); } } } int main() { read(); dfs(1,-1); printf("%d\n%d\n",block,acnt); for(int i=1;i<=acnt;i++) printf("%d %d\n",ans[i].p.first,ans[i].p.second); return 0; }
边的双连通即为删去割边后的连通块
**点双连通即为没有割点的块,边亦如是
相关文章推荐
- ORA-01033
- FlowLayout详解(一)——onMeasure()与onLayout()
- 原创 HTML5:JS操作SVG实践体会
- Unity官方教程学习笔记之Roll A Ball篇---(一)创建工程和保存场景
- Android中内容观察者的使用---- ContentObserver类详解
- $1...$9 属性 (RegExp) (JavaScript)
- 分布式系统 缓存穿透与失效时的雪崩效应
- Activity的几种启动模式介绍
- 黑马程序员——JAVA基础------集合框架(三)----Iterator
- Java 堆内存模型
- 通过EventBus更换android app主题
- crossApp初级-类的结构-2
- 【转】常见数字IC设计、FPGA工程师面试题
- 计算机视觉、机器学习相关领域论文和源代码大集合(非常实用)
- HDU 2895 贪心 还是 大水题
- pinyin4j新手教程
- JavaScript学习总结
- China Vis 2015 会议小结
- Dockerfile 中CMD 和 ENTRYPOINT指令
- 为什么用服务不用线程-Android