这就是一道裸题啊23333
时间限制: 1 Sec 内存限制: 64 MB
题目描述
给出一个无向连通图, 求出所有割点与割边的数量。
输入
第1行: 2个整数N,M (1 <= N <= 5,000,N-1 <= M <= 10,000),分别表示顶点数和边数
接下来M行,每行2个整数,表示图中的一条边。
输出
第1行:1个整数,表示割点数
第2行:1个整数,表示割边数
样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
11 13
1 2
1 4
1 5
1 6
2 11
2 3
4 3
4 9
5 8
5 7
6 7
7 10
11 3
样例输出
4
3
在这里顺便讲一讲割点和割边是什么和怎么求的好了...
先介绍几个概念:
dfn:在DFS时,用dfn[u]表示编号为u的节点在DFS过程中的访问序号(也叫做开始时间)。dfn[u]称为顶点u的深度优先数。显然,越先访问的节点dfn值越小。
树边/反向边(返祖边):
通常,当我们到达某个顶点u时,会有两种情况出现:
(1)如果存在与u关联的未被检查的边,那么我们就选择这样的边(u,v),并定向为从u到v。这时,边(u,v)就说成是被检查过。现在有两种情形都需要考虑:
情形1 如果顶点v原来未被访问过,那么我们就经过边(u,v)去访问v,并从v继续搜索。在这种情况下,(u,v)就是一条树边,且FATHER[v] = u。
情形2 如果顶点v原来已经被访问过,那么我们就继续选择一条与u关联的其它未检查过的边。在这种情况下,边(u, v)就称为一条反向边。
(2)如果与u关联的所有边都已检查过,那么我们返回到u的父亲,并继续从父亲结点的未检查过的邻接边搜索。顶点u这时就说成是完全扫描过。当搜索返回到起始顶点,并且所有的边都已经被检查过了,DFS就终止。
low:
我们通过DFS把无向图定向成有向图,定义每个顶点的low参数,low[u]表示沿u出发的有向轨能够到达的点v中,dfn[u]的最小值。(经过返祖边后则停止)
low[u]定义为u或者u的子树中能够通过非父子边追溯到的节点的DFS最早开始时间
low[u]的定义提供了如下的计算步骤:
1. 当u是DFS期间首次访问时,则low[u] = dfn[u]
2. 当与u关联的一条反向边(u,v)被检查时,low[u]= min{low[u], dfn[v]}
3. 当DFS在u的一个儿子v完全扫描后返回到u时,low[u] = min{low[u], low[v]}
割点:去掉后使图不连通的点。
割边:去掉后使图不连通的边。
求法:(详见后面代码)
割点:low[v]>=dfn[u](v最远也只能到它爸爸)
割边:low[v]>dfn[u](v已经回不到它的祖先了)
所以就直接上一段乱搞的AC代码吧..._(:з」∠)_
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,s[5005],dfn[5005],low[5005],gd,gb,t,rts,ctp[5005];
struct nde
{
int x,y;
}a[200005];
bool cmp(nde p,nde q){return p.x!=q.x?(p.x<q.x):(p.y<q.y);}
void dfs(int u,int f)
{
int i;
dfn[u]=low[u]=++t;
for(i=s[u];a[i].x==u;i++)
{
if(!dfn[a[i].y])
{
dfs(a[i].y,u);
low[u]=min(low[u],low[a[i].y]);
if(low[a[i].y]>dfn[u]) gb++;
if(low[a[i].y]>=dfn[u]&&!ctp[u]) //避免重复计数
{
if(f&&!ctp[u]) {gd++;ctp[u]=1;}
else rts++;
if(rts>1&&!f&&!ctp[u]) {gd++;ctp[u]=1;}
}
}
else if(a[i].y!=f) low[u]=min(low[u],dfn[a[i].y]);
}
}
int main()
{
int i;
scanf("%d%d",&n,&m);
for(i=1;i<=m*2;i+=2) {scanf("%d%d",&a[i].x,&a[i].y);a[i+1].x=a[i].y;a[i+1].y=a[i].x;}
sort(a+1,a+m*2+1,cmp);
for(i=1;i<=m*2;i++) if(a[i].x!=a[i-1].x) s[a[i].x]=i;
dfs(1,0);
printf("%d\n%d\n",gd,gb);
}
沦为高一狗之后就开始潜水了..23333偶尔冒个泡

本文介绍如何求解无向连通图中的割点与割边数量,通过深度优先搜索(DFS)算法,详细解释了割点与割边的概念及其判断条件。
974

被折叠的 条评论
为什么被折叠?



