POJ 3352-Road Construction (图论-双边联通分支算法)

题目大意:一个图,要求你加入最少的边,使得最后得到的图为一个边双连通分支。所谓的边双连通分支,即不存在桥的连通分支(题目保证数据中任意两点都联通)。

解题思路:先用tarjan算法进行缩点建立DAG图, 然后再进行寻找度为1的点有个数x, 那么需要添加的边即为(x+1)/ 2;

起初这样写, 一直WA,然后发现下面两个数据,发现并不能过。

#include <stdio.h>
#include <set>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1003;
vector<int>G[N];
vector<pair<int, int> >DAG;
int dfn[N], low[N], mk[N];
int tot;
int n, m;

void init()
{
    tot = 0;
    DAG.clear();
    for(int i=1; i<=n; ++ i)
    {
        mk[i] = 0;
        G[i].clear();
        dfn[i] = low[i] = -1;
    }
}

void tarjan(int u, int f)
{
    dfn[u] = low[u] = ++ tot;
    for(int i = 0; i < G[u].size(); ++ i)
    {
        int v = G[u][i];
        if(dfn[v] == -1)
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(dfn[u] < low[v])
                DAG.push_back(make_pair(low[u], low[v]));
        }
        else if(v != f)
            low[u] = min(low[u], dfn[v]);
    }
}

void solve()
{
    init();
    for(int i=1; i<=m; ++ i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    tarjan(1, -1);
    for(int i=0; i<DAG.size(); ++ i)
    {
        pair<int, int> S = DAG[i];
        mk[S.first] ++, mk[S.second] ++;
    }
    int ans = 0;
    for(int i=1; i<=n; ++ i)
    {
        if(mk[i] == 1)
            ans ++;
    }
    printf("%d\n", (ans + 1) / 2);
}

int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
        solve();
    return 0;
}

需要特别注意两组数据:

2 2

1 2

1 2

2 1

1 2

答案分别是:

0

1

代码如下:

#include <stdio.h>
#include <set>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1003;
vector<int>G[N];
int dfn[N], low[N], mk[N];
int tot;
int n, m;

void init()
{
    tot = 0;
    for(int i=1; i<=n; ++ i)
    {
        mk[i] = 0;
        G[i].clear();
        dfn[i] = low[i] = -1;
    }
}

void tarjan(int u, int f)
{
    dfn[u] = low[u] = ++ tot;
    for(int i = 0; i < G[u].size(); ++ i)
    {
        int v = G[u][i];
        if(dfn[v] == -1)
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else if(v != f)
            low[u] = min(low[u], dfn[v]);
    }
}

void solve()
{
    init();
    for(int i=1; i<=m; ++ i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    tarjan(1, -1);
    for(int i = 1; i <= n; ++ i)
    {
        for(int j = 0; j < G[i].size(); ++ j)
        {
            if(low[i] != low[G[i][j]])
                mk[low[i]] ++;
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; ++ i)
        if(mk[i] == 1)
            ans ++;
    printf("%d\n", (ans + 1) / 2);
}

int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
        solve();
    return 0;
}

时间: 2024-12-19 03:07:38

POJ 3352-Road Construction (图论-双边联通分支算法)的相关文章

POJ 3352 Road Construction(图论-tarjan)

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8647   Accepted: 4318 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

POJ 3352 Road Construction 使得无向图边变双连通图

点击打开链接 Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8168   Accepted: 4106 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

POJ 3177 Redundant Paths POJ 3352 Road Construction(双连通)

POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的,一份代码能交,给定一个连通无向图,问加几条边能使得图变成一个双连通图 思路:先求双连通,缩点后,计算入度为1的个数,然后(个数 + 1) / 2 就是答案(这题由于是只有一个连通块所以可以这么搞,如果有多个,就不能这样搞了) 代码: #include <cstdio> #include <cstring> #include <algorithm&

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点)

POJ 3352 Road Construction POJ 3177 Redundant Paths(边双连通图 Tarjan+缩点) ACM 题目地址: POJ 3352 Road Construction POJ 3177 Redundant Paths 题意: 问要添加几条边才能使所给无向图图变成边双连通图. 分析: 边连通度:使无向图G不连通的最少删边数量为其边连通度. 边双连通图:边连通度大于1的无向图. 首先缩点,让图变成一个DAG. 现在问题转化为:在树中至少添加多少条边能使图变

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 3352 Road Construction(无向连通图)

题目地址:POJ 3352 这题就是求最少加多少条边可以使得图为无向双连通图.方法是找度数为1的连通分量,可以只用low来找.然后根据公式(叶子结点数+1)/2即可得到答案.原因是在图中将每两个度数为1的都连起来,度数为2的显然已经可以形成双联通了,因为是无向边,只要加一条,就相当于加了两条有向边,很显然,结果数就是那个公式. 代码如下: #include <iostream> #include <cstdio> #include <string> #include &

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

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

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 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 r

POJ 3352 Road Construction

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 roads on the tropical island paradise of Remote Island would like to repair and upgrade the various roads that lead