zoukankan      html  css  js  c++  java
  • 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
    ", (ans + 1) / 2);
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
            solve();
        return 0;
    }
    View Code

    需要特别注意两组数据:

    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
    ", (ans + 1) / 2);
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
            solve();
        return 0;
    }
    View Code
  • 相关阅读:
    HYSBZ 1500 [NOI2005]维修数列 splay
    The 15th Zhejiang University Programming Contest
    工作小助手-v1.0正式上线,欢迎体验!!!
    登录窗体登录失败但是MainForm依然弹出无法结束的解决方法
    报错'cannot change visible in onshow or onhide'
    release模式发布软件的方法
    发布软件时因为窗体自动加载次序不对导致报错00000000
    修改类别 (类实现)两种方法
    从记事本导入记录
    快速粘贴
  • 原文地址:https://www.cnblogs.com/aiterator/p/5935445.html
Copyright © 2011-2022 走看看