Hihocoder#1183 : 连通性一·割边与割点(连通图求割点和割边)

2024-01-25 10:32

本文主要是介绍Hihocoder#1183 : 连通性一·割边与割点(连通图求割点和割边),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢失。为了避免再次出现这样的情况,学校决定对校园网络进行重新设计。

学校现在一共拥有N台服务器(编号1..N)以及M条连接,保证了任意两台服务器之间都能够通过连接直接或者间接的数据通讯。

当发生黑客攻击时,学校会立刻切断网络中的一条连接或是立刻关闭一台服务器,使得整个网络被隔离成两个独立的部分。

举个例子,对于以下的网络:

每两个点之间至少有一条路径连通,当切断边(3,4)的时候,可以发现,整个网络被隔离为{1,2,3},{4,5,6}两个部分:

若关闭服务器3,则整个网络被隔离为{1,2},{4,5,6}两个部分:

小Hi和小Ho想要知道,在学校的网络中有哪些连接和哪些点被关闭后,能够使得整个网络被隔离为两个部分。

在上面的例子中,满足条件的有边(3,4),点3和点4。

 

提示:割边&割点

 
输入

第1行:2个正整数,N,M。表示点的数量N,边的数量M。1≤N≤20,000, 1≤M≤100,000

第2..M+1行:2个正整数,u,v。表示存在一条边(u,v),连接了u,v两台服务器。1≤u<v≤N

保证输入所有点之间至少有一条连通路径。

输出

第1行:若干整数,用空格隔开,表示满足要求的服务器编号。从小到大排列。若没有满足要求的点,该行输出Null

第2..k行:每行2个整数,(u,v)表示满足要求的边,u<v。所有边根据u的大小排序,u小的排在前,当u相同时,v小的排在前面。若没有满足要求的边,则不输出



样例输入
6 7
1 2
1 3
2 3
3 4
4 5
4 6
5 6
样例输出
3 4
3 4

       模板题,连通图求割点和割边。原理截取Hiho的解释。存个模板

割边:在连通图中,删除了连通图的某条边后,图不再连通。这样的边被称为割边,也叫做桥。

割点:在连通图中,删除了连通图的某个点以及与这个点相连的边后,图不再连通。这样的点被称为割点。

DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树。在上面例子中,得到的搜索树为:

树边:在搜索树中的蓝色线所示,可理解为在DFS过程中访问未访问节点时所经过的边,也称为父子边

回边:在搜索树中的橙色线所示,可理解为在DFS过程中遇到已访问节点时所经过的边,也称为返祖边、后向边

观察DFS搜索树,我们可以发现有两类节点可以成为割点:

  • 对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;

  • 对非叶子节点u(非根节点),若其中的某棵子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与该棵子树的节点不再连通;则节点u为割点。

对于根结点,显然很好处理;但是对于非叶子节点,怎么去判断有没有回边是一个值得深思的问题。

我们用dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小),那么low[u]的计算过程如下:

对于给的例子,其求出的dfn和low数组为:

id  1 2 3 4 5 6
dfn 1 2 3 4 5 6
low 1 1 1 4 4 4

可以发现,对于情况2,当(u,v)为树边且low[v]≥dfn[u]时,节点u才为割点。

而当(u,v)为树边且low[v]>dfn[u]时,表示v节点只能通过该边(u,v)与u连通,那么(u,v)即为割边。

void dfs(int u) {//记录dfs遍历次序static int counter = 0;	//记录节点u的子树数int children = 0;ArcNode *p = graph[u].firstArc;visit[u] = 1;//初始化dfn与lowdfn[u] = low[u] = ++counter;for(; p != NULL; p = p->next) {int v = p->adjvex;//节点v未被访问,则(u,v)为树边if(!visit[v]) {children++;parent[v] = u;dfs(v);low[u] = min(low[u], low[v]);//case (1)if(parent[u] == NIL && children > 1) {printf("articulation point: %d\n", u);}//case (2)if(parent[u] != NIL && low[v] >= dfn[u]) {printf("articulation point: %d\n", u);}//bridgeif(low[v] > dfn[u]) {printf("bridge: %d %d\n", u, v);}}//节点v已访问,则(u,v)为回边else if(v != parent[u]) {low[u] = min(low[u], dfn[v]);}}
}
原题代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
vector<int>V[20005];
int ansNode[20005];
int dfn[20005];
int low[20005];
int visit[20005];
int parent[20005];
int have[20005];
int nn;
int nPoint;
int counter;	//记录dfs遍历次序
struct Bi
{int u,v;
}B[100005];
bool  cmp(Bi a,Bi b)
{if(a.u!=b.u)return a.u<b.u;elsereturn a.v<b.v;
}
void dfs(int u) {//记录节点u的子树数int children = 0;visit[u] = 1;//初始化dfn与lowdfn[u] = low[u] = ++counter;for(int i=0;i<V[u].size();i++) {int v = V[u][i];//节点v未被访问,则(u,v)为树边if(!visit[v]) {children++;parent[v] = u;dfs(v);low[u] = min(low[u], low[v]);//case (1)if(parent[u] == 0 && children > 1) {//printf("articulation point: %d\n", u);if(have[u]==0){ansNode[nPoint++]=u;have[u]=1;}}//case (2)if(parent[u] != 0L && low[v] >= dfn[u]) {//printf("articulation point: %d\n", u);if(have[u]==0){ansNode[nPoint++]=u;have[u]=1;}}//bridgeif(low[v] > dfn[u]) {//printf("bridge: %d %d\n", u, v);if(u<v){B[nn++].u=u;B[nn-1].v=v;}else{B[nn++].u=v;B[nn-1].v=u;}}}//节点v已访问,则(u,v)为回边else if(v != parent[u]) {low[u] = min(low[u], dfn[v]);}}
}
int main()
{int n,m;while(~scanf("%d%d",&n,&m)){memset(parent,0,sizeof(parent));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(visit,0,sizeof(visit));memset(have,0,sizeof(have));nn=0;nPoint=0;counter=0;for(int i=0;i<=n;i++){V[i].clear();}int u,v;for(int i=0;i<m;i++){scanf("%d%d",&u,&v);V[u].push_back(v);V[v].push_back(u);}dfs(1);sort(ansNode,ansNode+nPoint);if(nPoint==0)cout<<"Null"<<endl;else{cout<<ansNode[0];for(int i=1;i<nPoint;i++){cout<<" "<<ansNode[i];}cout<<endl;}sort(B,B+nn,cmp);for(int i=0;i<nn;i++){cout<<B[i].u<<" "<<B[i].v<<endl;}}
}




这篇关于Hihocoder#1183 : 连通性一·割边与割点(连通图求割点和割边)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/642990

相关文章

图的割点、割线问题

图的割点问题 邻接矩阵表示图 package com.hyl.algorithm.other;import java.util.Arrays;import com.hyl.algorithm.search.base.SearchIntf;import com.hyl.algorithm.search.base.SearchIntfFactory;/*** 寻找图的割点* <p>** @aut

像素间的关系(邻接、连通、区域、边界、距离定义)

文章目录 像素的相邻像素4邻域D邻域8邻域 邻接、连通、区域和边界邻接类型连通区域边界 距离测度欧氏距离城市街区距离(city-block distance)棋盘距离(chessboard distance) 参考 像素的相邻像素 4邻域 坐标 ( x , y ) (x,y) (x,y)处的像素 p p p有2个水平的相邻像素和2个垂直的相邻像素,它们的坐标是: ( x

OpenCV结构分析与形状描述符(6)带统计的连通组件计算函数connectedComponentsWithStats()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 connectedComponentsWithStats 函数计算布尔图像的连通组件标记图像,并为每个标记产生统计信息。 该函数接受一个具有4或8连通性的二值图像,并返回 N,即标签总数(标签范围为 [0, N-1],其中 0 代表背景标签)

最小连通网络

使用网络中的n-1条边来连接网络中的n个顶点 不产生回路 各边上的权值总和达到最小 prim算法:针对顶点展开,适合边的数量较多的情况 kruskal算法:针对边展开的,适合边的数量较少的情况

nc -s网络连通性测试

例如: nc -s 192.168.82.67 192.168.82.66 22 在这个命令中,您使用了nc(Netcat)工具来进行网络连接。下面是命令的详细说明: nc: 表示使用Netcat工具进行操作。-s 192.168.82.67: 指定源IP地址为192.168.82.67。这个参数让Netcat使用指定的IP地址进行网络连接,而不是默认的地址。192.168.82.66:

【HDU】2242 考研路茫茫——空调教室 双连通分量+树型DP

考研路茫茫——空调教室 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1978    Accepted Submission(s): 576 Problem Description 众所周知,HDU的考研教室是没

【HDU】3861 The King’s Problem 强连通缩点+有向图最小路径覆盖

传送门:【HDU】3861 The King’s Problem 题目分析:首先强连通缩点,因为形成一个环的王国肯定在一条路径中,这样才能保证拆的少。 然后缩点后就是DAG图了,由于题目要求的是最小路径覆盖,那么二分匹配即可。 代码如下: #include <cstdio>#include <cstring>#include <algorithm>#includ

【ZOJ】2532 Internship 最小割——关键割边

传送门:【ZOJ】2532 Internship 题目分析:题目意思很明显,问你能否增加一条边的容量使得流量增加,就是让求关键割边。关键割边怎么求?首先按照题意建图跑一遍最小割。之后在残余网络上进行dfs,将从源点s出发能到的点标记为1,将从汇点t出发能到的点重标记为2。一条边为关键割边当且仅当它为正向边且弧头标记为1,弧尾标记为2。 PS:注意dfs的细节,s出发沿正向残余网络,t出发

【Live Archive】6393 Self-Assembly【强连通】

传送门:【Live Archive】6393 Self-Assembly 题目分析: 假设我们只用到向上或者向右的块,这样我们只要找到一个回路使得某个块可以和第一个块一样,那么我们就相当于找到了一个循环,这样就可以无限循环了。 但是我们要怎样去找这么一个环?考虑到必须是对应字母 X+,X− X^+,X^-才能建边,然后一个环中一定是多个一对一对的这样的对应字母组成的。 可以发现块的数量那么

OpenCV_连通区域分析(Connected Component Analysis-Labeling)

申明:本文非笔者原创,原文转载自:http://blog.csdn.net/icvpr/article/details/10259577 OpenCV_连通区域分析(Connected Component Analysis/Labeling) 【摘要】 本文主要介绍在CVPR和图像处理领域中较为常用的一种图像区域(Blob)提取的方法——连通性分析法(连通区域标