zoukankan      html  css  js  c++  java
  • POJ3177 POJ3352 加最少的边构成双连通图

    /*
    *State: POJ3177    Accepted    340K    16MS    C++    1877B
    *题目大意:
    *        给出一个无向连通图,判断最少需要加多少条边,才能使得
    *        任意两点之间至少有两条相互"边独立"的道路.注意,可能
    *        含有重边.
    *解题思路:
    *        先缩点,之后形成一棵树,然后求(叶子节点数量+1)/ 2即可。
    */
    View Code
    #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;
    
    const int MAXN = 5005;
    const int MAXE = 10005;
    
    vector<int> vec[MAXN];
    stack<int> S;
    int dfn[MAXN], low[MAXN], step;
    int id[MAXN], scc;
    
    void init()
    {
        while(!S.empty())
            S.pop();
    
        step = 0;
        scc = 1;
        for(int i = 0; i < MAXN; i++)
        {
            id[i] = -1;
            vec[i].clear();
            dfn[i] = low[i] = -1;
        }
    }
    
    void addEdge(int u, int v)
    {
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    
    void tarjan_scc(int n, int father)
    {
        dfn[n] = low[n] = ++step;
        S.push(n);
        int flag = 0;
        for(unsigned i = 0; i < vec[n].size(); i++)
        {
            int son = vec[n][i];
            if(son == father && !flag)
            {
                flag = 1;
                continue;
            }
    
            if(dfn[son] == -1)
            {
                tarjan_scc(son, n);
                low[n] = min(low[n], low[son]);
            }
            else
                low[n] = min(low[n], dfn[son]);
        }
    
        if(low[n] == dfn[n])
        {
            int tmp;
            do
            {
                tmp = S.top();
                id[tmp] = scc;
            //    cout << tmp << " ";
                S.pop();
            }while(!S.empty() && tmp != n);
            scc++;
            //cout << endl << "---------------" << endl;
        }
    }
    
    void deal_scc(int n, int &sol)
    {
        int u, v;
        int du[MAXN] = {0};
        for(int i = 1; i <= n; i++)
        {
            for(unsigned j = 0; j < vec[i].size(); j++)
            {
                u = i, v = vec[i][j];
                if(id[u] == id[v])
                    continue;
                else
                {
                    du[id[v]]++; du[id[u]]++;
                }
            }
        }
        int sum = 0;
        for(int i = 1; i < scc; i++)
        {
            if(du[i] == 2)
                sum++;
        }
        sum++;
        sol = sum / 2;
    }
    
    int main(void)
    {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
    #endif
    
        int n, m;
        while(scanf("%d %d", &n, &m) == 2)
        {
            init();
            int u, v;
            for(int i = 0; i < m; i++)
            {
                scanf("%d %d", &u, &v);
                addEdge(u, v);
            }
            tarjan_scc(1, 1);
            int sol;
            deal_scc(n, sol);
            printf("%d\n", sol);
            //cout << "****************" << endl;
        }
        return 0;
    }
    //POJ3352
    //State: POJ3352    Accepted    280K    47MS    C++    1865B
    //题意与上述的题一模一样
    View Code
    #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;
    
    const int MAXN = 1005;
    
    vector<int> vec[MAXN];
    stack<int> S;
    int dfn[MAXN], low[MAXN], step;
    int id[MAXN], scc;
    
    void init()
    {
        while(!S.empty())
            S.pop();
    
        step = 0;
        scc = 1;
        for(int i = 0; i < MAXN; i++)
        {
            id[i] = -1;
            vec[i].clear();
            dfn[i] = low[i] = -1;
        }
    }
    
    void addEdge(int u, int v)
    {
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    
    void tarjan_scc(int n, int father)
    {
        dfn[n] = low[n] = ++step;
        S.push(n);
        int flag = 0;
        for(unsigned i = 0; i < vec[n].size(); i++)
        {
            int son = vec[n][i];
            if(son == father && !flag)
            {
                flag = 1;
                continue;
            }
    
            if(dfn[son] == -1)
            {
                tarjan_scc(son, n);
                low[n] = min(low[n], low[son]);
            }
            else
                low[n] = min(low[n], dfn[son]);
        }
    
        if(low[n] == dfn[n])
        {
            int tmp;
            do
            {
                tmp = S.top();
                id[tmp] = scc;
            //    cout << tmp << " ";
                S.pop();
            }while(!S.empty() && tmp != n);
            scc++;
            //cout << endl << "---------------" << endl;
        }
    }
    
    void deal_scc(int n, int &sol)
    {
        int u, v;
        int du[MAXN] = {0};
        for(int i = 1; i <= n; i++)
        {
            for(unsigned j = 0; j < vec[i].size(); j++)
            {
                u = i, v = vec[i][j];
                if(id[u] == id[v])
                    continue;
                else
                {
                    du[id[v]]++; du[id[u]]++;
                }
            }
        }
        int sum = 0;
        for(int i = 1; i < scc; i++)
        {
            if(du[i] == 2)
                sum++;
        }
        sum++;
        sol = sum / 2;
    }
    
    int main(void)
    {
    #ifndef ONLINE_JUDGE
        freopen("in3352.txt", "r", stdin);
    #endif
    
        int n, m;
        while(scanf("%d %d", &n, &m) == 2)
        {
            init();
            int u, v;
            for(int i = 0; i < m; i++)
            {
                scanf("%d %d", &u, &v);
                addEdge(u, v);
            }
            tarjan_scc(1, 1);
            int sol;
            deal_scc(n, sol);
            printf("%d\n", sol);
            //cout << "****************" << endl;
        }
        return 0;
    }
  • 相关阅读:
    ubuntu 14.04 firefox install flash-plugin
    ubuntu node.js Binaries方式安装(二进制文件安装)
    ubuntu14.04 截图
    ubuntu 14.04下,thinkpad触摸板关闭方法
    ubuntu Mozilla Firefox install flash plugin 火狐浏览器安装flash插件
    win7+ubuntu 14.04双系统 硬盘安装
    后台启动VirtualBox虚拟机
    excel vlookup函数使用方法
    图片添加文字水印和图片水印
    记录使用Stream转多层map数据结构及遇到的坑
  • 原文地址:https://www.cnblogs.com/cchun/p/2645075.html
Copyright © 2011-2022 走看看