@[双连通分量]

题意:

有一个 n 个点 m 条边的无向图,问至少添加几条边,能让该图任意缺少一条边后还能相互连通。

双连通分量定义:

在无向连通图中,如果删除该图的任何一个结点都不能改变该图的连通性,则该图为双连通的无向图。一个连通的无向图是双连通的,当且仅当它没有关节点(这里面节点可换成边:分点双连通分量 ,分边双连通分量)。

思路:

首先缩点成树;

与强连通分量缩点有所不同:记录父节点 ,不返回父节点 (意味着一条边只能从任意方向走一次)如果已经走过 ,直接可更新low值(目前理解:若这个点 B 已经走过,出栈后还能再次通过 A 访问到,说明从 B 也能访问到 A ,所以不需要是否在栈中的判断,在强连通分量中,因为是单向,所以只能从 A -> B ,需要是否在栈中的判断)

试了一下加上栈的判断也对:因为访问B的时候直接就通过B 把 A 访问了,不会等到 A 去访问 B 。

缩点成树之后:

统计有 ans 个双连通分量只有一条边且只与一个双连通分量相连,(ans+1)/2 就是至少要加的边数

撸代码

#include<stdio.h>
#include<string.h>
#include<stack>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1010
struct node
{
    int to,nex;
} edge[N*2];
int cost[N],dfn[N],low[N],belong[N],head[N];
bool instack[N];
int in[N];
int cnt,cir,index;
stack<int>s;
vector<int>point[N];
void init()
{
    cnt=0;
    cir=0;
    index=0;
    while(!s.empty())
        s.pop();
    for(int i=0; i<N; i++)
    {
        point[i].clear();
        head[i]=-1;
        in[i]=0;
        instack[i]=false;
        dfn[i]=0;
        low[i]=0;
        belong[i]=0;
    }
}
void addEdge(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].nex=head[u];
    head[u]=cnt++;
}
/*求双连通分量*/
void Tarjan(int u,int fa)
{
    dfn[u]=low[u]=++index;
    instack[u]=true;
    s.push(u);
    for(int i=head[u]; i!=-1; i=edge[i].nex)
    {
        int v=edge[i].to;
        if(v==fa)
            continue;
        if(!dfn[v])
        {
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else //if(instack[v])
        {/*走过且不在栈中*/
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        int node;
        ++cir;
        do
        {
            node=s.top();
            s.pop();
            belong[node]=cir;
            point[cir].push_back(node);
            instack[node]=false;
        }
        while(node!=u);
    }
    return ;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        int a,b;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&a,&b);
            addEdge(a,b);
            addEdge(b,a);
        }
        for(int i=1; i<=n; i++)
            if(!dfn[i])
                Tarjan(i,i);
        /*直到每个点所属的强连通分量*/
//        printf("cir = %d\n",cir);
//        for(int i=1;i<=cir;i++)
//        {
//            printf("cnt [%d]:",i);
//            for(int j=0;j<point[i].size();j++)
//                printf("%d ",point[i][j]);
//            printf("\n");
//        }
        for(int i=1; i<=n; i++)
        {
            for(int j=head[i]; j!=-1; j=edge[j].nex)
            {
                /*!根据统计边 统计连通分量之间的度*/
                a=belong[i];
                b=belong[edge[j].to];
                if(a!=b)
                {
                    in[a]++;
                    in[b]++;
                }
            }
        }
        int ans=0;
        for(int i=1; i<=cir; i++)
        {
            if(in[i]==2)
                ans++;
        }
        printf("%d\n",(ans+1)/2);
    }
    return 0;
}

双连通分量 Road Construction POJ - 3352的更多相关文章

  1. Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)

     http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...

  2. POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

  3. POJ 3352 Road Construction(边—双连通分量)

    http://poj.org/problem?id=3352 题意: 给出一个图,求最少要加多少条边,能把该图变成边—双连通. 思路:双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相 ...

  4. POJ 3352 Road Construction(边双连通分量,桥,tarjan)

    题解转自http://blog.csdn.net/lyy289065406/article/details/6762370   文中部分思路或定义模糊,重写的红色部分为修改过的. 大致题意: 某个企业 ...

  5. POJ 3352 Road Construction (边双连通分量)

    题目链接 题意 :有一个景点要修路,但是有些景点只有一条路可达,若是修路的话则有些景点就到不了,所以要临时搭一些路,以保证无论哪条路在修都能让游客到达任何一个景点 思路 :把景点看成点,路看成边,看要 ...

  6. POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)

    POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...

  7. POJ 3352 Road Construction 双联通分量 难度:1

    http://poj.org/problem?id=3352 有重边的话重边就不被包含在双连通里了 割点不一定连着割边,因为这个图不一定是点连通,所以可能出现反而多增加了双连通分量数的可能 必须要用割 ...

  8. poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&&缩点】

    Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 503 ...

  9. POJ3352 Road Construction (双连通分量)

    Road Construction Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Sub ...

随机推荐

  1. Java 集合、数组排序

    在平时开发的过程中,经常会遇到需要对数组.集合中元素按规则进行排序,本文记录在开发过程中可能遇到的情况以及相关的完整代码示例. 知识点 Comparable<T>接口 实现了该接口的对象, ...

  2. 当微信小程序遇上filter~

    在微信小程序的开发过程中,当你想要实现不同页面间的数据绑定,却为此抓耳饶腮时,不妨让微信小程序与filter 来一场完美的邂逅,相信会给你带来别样的惊喜~ 前段时间被安利了一个很实用的公众号-前端早读 ...

  3. 前端每日实战:151# 视频演示如何用纯 CSS 创作超能陆战队的大白

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/ReGRaO 可交互视频 此视频是可 ...

  4. python之嵌套 闭包 装饰器 global、nonlocal关键字

    嵌套: 在函数的内部定义函数闭包: 符合开放封闭原则:在不修改源代码与调用方式的情况下为函数添加新功能  # global 将局部变量变成全局变量 num = 100 def fn1(): globa ...

  5. 02 layui 下载和搭建环境

    Layui官方网站 官方网站:https://www.layui.com/ 下载地址:https://res.layui.com/static/download/layui/layui-v2.5.5. ...

  6. 在Deepin系统上装Python 3.8遇到的那些坑

    - 作为一天时间在Deepin上都没装好Python的代表,我感觉有必要记录一下我自己的解决方法 坑1-- SSL/TLS 字样错误 "pip is configured wih locat ...

  7. Git的使用流程及常用命令汇总

    Git是一个很好用的版本控制系统,本文对于常用的一些命令进行了汇总. 创建一个存储仓库(repository) https://github.com/右上角点击"+"号,New r ...

  8. 【09】openlayers 图片图层

    效果:  创建地图: var map = new ol.Map({ //设置显示地图的视图 view: new ol.View({ projection:'EPSG:4326',//投影方式 cent ...

  9. c 将年月日转化为星期

    /*得到年月日转化为星期几*/ LOCAL ulong_t DateWeekGet(ulong_t year,ulong_t month,ulong_t day) { ulong_t c = ; ul ...

  10. python3.4.3 调用http接口 解析response xml后插入数据库

    工作中需要调用一个http的接口,等不及java组开发,就试着用python去调用.Python版本3.4.3 完整的流程包括:从sqlServer取待调用的合同列表 -> 循环调用http接口 ...