poj 3177 边的双连通分支

/********************************************************************
 ** @file    poj3177.cpp
 ** @author  liuke
 ** @date    Sun May  1 09:49:13 2011
 ** @brief   边的双连通分量问题
首先是根据割边求出所有点的双连通分量,然后进行缩点。
然后对缩点后的图看度数为一的顶点可以有多少个。然后添加的边数即为(n+1)/ 2条。
 **    
 **     
 ********************************************************************/
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#define MAXN 5001
#define WHITE 0
#define GRAY 1
#define BLACK 2
using namespace std;
vector<int> g[MAXN];
int f,r, c[MAXN], dfn[MAXN], low[MAXN], cnt;
int t[MAXN];
void input(){
  cin>>f>>r;
  int u,v;
  for(int i=0;i<r;++i){
    cin>>u>>v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
}
void dfs(int v,int f){/*f 为v的父节点*/
  bool flag=true;
  c[v]=GRAY;
  low[v]=dfn[v]=++cnt;
  for(int i=0;i<g[v].size();++i){
    int u=g[v][i];
    if(u==f && flag==true){
      flag=false;continue;/*防止往回走*/
    }
    if(c[u]==WHITE)
      dfs(u,v);
    low[v]=min(low[v],low[u]);/*缩点*/
  }
  c[v]=BLACK;
}
int solve(){

  cnt=0;
  memset(t,0,sizeof(t));
  memset(c,WHITE,sizeof(c));
  dfs(1,-1);
  for(int i=1;i<=f;++i){
    for(int j=0;j<g[i].size();++j)
      if(low[i]!=low[g[i][j]])
        t[low[i]]++;/*缩点后的 对应的各个双连通分支的度加1,low[i]代表了各个连通分支*/
  }
  int ans=0;
  for(int i=1;i<=f;++i)
    if(t[i]==1)ans++;/*统计度为1的节点,缩点后的分支会算一个节点,因为它们的low值相同*/
  return (ans+1)/2;
}
int main(int argc, char *argv[])
{
  input();
  cout<<solve()<<endl;
  return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值