码迷,mamicode.com
首页 > 其他好文 > 详细

关节点

时间:2019-09-28 01:16:47      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:bit   art   存在   play   timer   检查   cto   bool   max   

定义

在连通图 G 中,如果删除顶点 u 及从 u 出发的所有边后所得的子图不连通,我们就称顶点 u 为图 G 的关节点或连接点。 

原理

  要解决这道题,我们可以检查图在单独删除各顶点之后的连通性,但这个算法要对每个顶点执行一次DFS, 效率不高。

  不过,只要我们如下将DFS加以应用,就可以有效地找出图 G 中所有的关节点了。

  在一次DFS中求以下变量值。

  ??prenum[u]:以 G 的任意顶点作为起点进行DFS,将各顶点 u 的访问(首次发现)顺序记录在prenum[u]中。

  ??parent[u]:通过DFS生成一棵树(DFS Tree),将其中结点 u 的父节点记录在parent[u]中。这里将DFS Tree记作T。

  ??lowest[u]:对于各顶点 u,计算下列情况的最小值并记入lowest[u]

     ① prenum[u]

     ② 存在 G 的Back(u, v)时,顶点 v 的prenum[v](Back(u, v)表示图 G 内 ”从顶点 u 出发指向 T 内的顶点 v“ 且 ”不属于 T “的边)

     ③ T 内顶点 u 的所以子节点 x 的lowest[u]

  有了这些变量,我们便可以通过下述方法确定关节点。

  ① T 的根节点 r 拥有 2 个以上子节点时(充分必要条件),r 为关节点。

  ② 对于各顶点 u,设 u 的父节点parent[u] 为 p ,如果prenum[p] <= lowest[u] (充分必要条件),则 p 为关节点(p 为根节点时则套用 ①)。这表明顶点 u 及 u 在 T 中的子孙均不具备与 p 的祖先相连的边。

实现

如图,G 代表图 G,T 代表以顶点 0 为起点对 G 执行DFS后得到的DFS Tree。T 的Back edges 用虚线标出,各顶点 u 的左侧数字为prenum[u]:lowest[u]。prenum[u]为DFS中各顶点 u 的被访问顺序:按照 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7的顺序记录。

lowest[u]是DFS过程中各顶点 u 访问结束的顺序:按照 4 -> 7 -> 6 -> 5 -> 3 -> 2 -> 1 -> 0的顺序算出。

技术图片

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000;
vector<int> G[maxn];
bool vis[maxn];
int N,prenum[maxn],parent[maxn],lowest[maxn],timer=1;
void dfs(int current,int prev);
void art_points();
int main()
{
  int i,m,s,t;
  cin>>N>>m;
  for(i=0;i<m;i++)
  {
    cin>>s>>t;
    G[s].push_back(t);
    G[t].push_back(s);
  }
  art_points();
  system("pause");
  return 0;
}
void art_points()
{
  int i,np=0,p;
  set<int> ap;
  dfs(0,-1);
  for(i=1;i<N;i++)
  {
    p=parent[i];
    if(p==0) np++;
    else if(prenum[p]<=lowest[i]) ap.insert(p);
  }
  if(np>1) ap.insert(0);
  for(set<int>::iterator it=ap.begin();it!=ap.end();it++)
   cout<<*it<<endl;
}
void dfs(int current,int prev)
{
  int next,i;
  prenum[current]=lowest[current]=timer;
  timer++;
  vis[current]=1;
  for(i=0;i<G[current].size();i++)
  {
    next=G[current][i];
    if(!vis[next])
    {
      parent[next]=current;
      dfs(next,current);
      lowest[current]=min(lowest[current],lowest[next]);
    }
    else if(next!=prev)
      lowest[current]=min(lowest[current],prenum[next]);
  }
}

关节点

标签:bit   art   存在   play   timer   检查   cto   bool   max   

原文地址:https://www.cnblogs.com/VividBinGo/p/11600998.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!