poj 3177 3352 边双连通分量

题目链接:http://poj.org/problem?id=3177

题意:至少加多少边才能构成边双连通图。

思路:求边双连通分量,对于每一个边双连通分量都看做一个点,也就是进行缩点,然后就构造出一个树,然后在这个树上加多少个树边,能够变成一个双连通图。 加的数量就是( 这棵树总度数为1的结点数 + 1 )/ 2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
const int M_node = 5009,M_edge = 20009;
struct edge
{
    int to,next;
    bool cut;
}edge[M_edge];
stack<int> st;
int head[M_node],tot;
int low[M_node],dfn[M_node],belong[M_node];
int degree[M_node];
int dfs_clock,block,bridge;
bool instack[M_node];
int n,m;
void init()
{
    while(!st.empty()) st.pop();
    memset(head,-1,sizeof(head));
    memset(degree,0,sizeof(degree));
    tot = 0;
    memset(instack,false,sizeof(instack));
    memset(belong,-1,sizeof(belong));
    dfs_clock = 0;
    block = bridge = 0;
}
void add_edge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cut = false;
    head[u] = tot++;
}
void tarjan(int u,int fa)
{
    low[u] = dfn[u] = ++dfs_clock;
    st.push(u);
    instack[u] = true;
    for(int i = head[u]; i != -1 ;i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == fa) continue;
        if(!dfn[v])
        {
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] > dfn[u])
            {
                bridge++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }
        }
        else if(instack[u] && low[u] > dfn[v]) low[u] = dfn[v];
    }
    if(low[u] == dfn[u])
    {
        block++;
        for(;;)
        {
            int v = st.top();
            st.pop();
            instack[v] = false;
            belong[v] = block;
            if(v == u) break;
        }
    }
}
void solve()
{
    int ans = 0;
    tarjan(1,-1);
    for(int i = 1;i <= n;i++)
    {
        for(int j = head[i];j != -1;j = edge[j].next)
        {
            if(edge[j].cut) degree[belong[i]]++;
        }
    }
    for(int i = 1;i <= block;i++)
    {
        if(degree[i] == 1) ans++;
    }
    printf("%d\n",(ans+1)/2);
}
int main()
{
    while(scanf("%d %d",&n,&m) == 2)
    {
        init();
        for(int i = 0;i < m;i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            add_edge(a,b);
            add_edge(b,a);
        }
        solve();
    }
    return 0;
}
时间: 2024-10-13 07:54:48

poj 3177 3352 边双连通分量的相关文章

POJ 3177 - Redundant Paths - 双连通分量

题目大意: 给定一个N个点,M条边的无向连通图(可能有重边),要求让任意两点间都有两条或以上的路径,且这些路径没有公共边.问至少需要加多少条边? N<=5e3,M<=1e4. 求双连通分量并缩点.详见:https://www.cnblogs.com/frog112111/p/3367039.html 注意由于本题数据允许重边(尽管讨论区有人吐槽数据太水),DFS时判断割边的条件应为low[to] > dfn[cur],且该边的重数为1. 实现的时候用了并查集来维护属于同一双联通分量的点,

Redundant Paths POJ - 3177(边—双连通分量)

题意: 在图中加边 看最少能通过加多少条边把 图变成边-双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的  注意重边 缩点 统计度为1的点  那么需要加的边为(ret+1)/2 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include

poj 3177 &amp; 3352 【无向图双连通分量Tarjan】

题目:poj 3177 & 3352 题意:大概意思就是给你一个无向图,让你添加最少的边,让所有点都双连通. 分析:双连通的定义就是任意两个点至少有两条路可达. 其实做法跟添加最少边强连通一样,先对图中已经双连通的缩点,然后重新编号. 这就是著名的Tanjan算法. 通过搜索的思想对所有存在环的边遍相同的号 如果要让所有的点双连通,那么对于缩点后的图中如果度数为 1 的话,这些边肯定要连接到其他的点才能双连通,而题目要求添加最少,所以连接到其他度数也为 1 的点是最优的,那么答案就是(odd+1

poj 3177 Redundant Paths (双联通)

/******************************************************* 题目:Redundant Paths (poj 2177) 链接:http://poj.org/problem?id=3177 算法:双联通+缩点 思路:先找出所有双联通分量,把这些分量缩成一个点 再找出所有度为一的点,用这些点数加一除2就可以了 ********************************************************/ #include<cs

Redundant Paths POJ - 3177(边双连通)

Redundant Paths POJ - 3177 题意:一个无向图(有重边!!),问至少还要加多少边使得去掉任意一条边后任意两点仍可互达. 和上题poj3352基本相同,不过dfs的时候,不能用v!=f来判断是否能走,而要用当前走的边和上一条边是不是反向边 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namesp

POJ 3352 Road Construction&amp;&amp; POJ 3177 Redundant Paths 双联通分量

大意:给定n点,和m条边的关系图中的一些边随时可能施工导致不能够通过,所以至少加多少条边才能够使得途中任意两条边联通? 思路:很明显只要图中的任意两点都是两条边来链接即可.那么我们可以先缩点构建新图,然后统计出度为1的点的个数ans,那么需要加的边数就是(ans+1)/2条; (PS;因为建图是双向的图所以,在Tarjan缩点的时候就需要遇到临边便越过,并且判断是不是同一个联通分支用num比较!) #include<map> #include<queue> #include<

poj 1144 Network【双连通分量求割点总数】

Network Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11042   Accepted: 5100 Description A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N

POJ 3352 &amp; 3177 无向图的边-双连通分量(无重边 &amp; 重边)

无向图的边-双连通分量 无向图的双连通分量实际上包含两个内容:点-双连通分量.边-双连通分量 点-双连通分量是指:在该连通分量里面,任意两个点之间有多条点不重复的路径(不包括起点.终点) 边-双连通分量是指:在该连通分量里面,任意两个点之间有多条边不重复的路径 在求解点-双连通分量时,无向图有没有重边都没有关系,因为一个点只能经过一次(有重边也无妨) 该篇文章并不深入讨论点-双连通分量,给出代码给有兴趣的参考参考:(也可以看看POJ2942这道题, 解题报告) /*===============

Poj 3352 Road Construction &amp; Poj 3177 Redundant Paths(边双连通分量+缩点)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9465   Accepted: 4699 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the ro