zoukankan      html  css  js  c++  java
  • Redundant Paths---poj3177(双连通分量)

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

    题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但

    可以经过同一个中间顶点。

    要先将图 强联通分量缩点, 在无向图中我们称为边双连通分量
     
    将所有边双连通分量求出来缩成点,就形成了一棵树,我们只要判断树的叶子结点的个数就行了。假设叶子节点的个数是 n  那么 就有 (n+1)/2 条边就能将这个图变成没有桥的 双连通图,判断一个点是否是叶子节点
     
    只要判断这个点的度就行了,度为 1 的点就是叶子节点。
     
    因此我们只需将叶子节点连在一起就可以了,需要建立(叶子节点的个数+1)/ 2;
     
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <cstring>
    using namespace std;
    #define INF 0xfffffff
    #define N 5100
    int low[N], dfn[N], f[N], block[N],du[N], Is[N];
    vector<vector<int> > G;
    int n, Time, m, cnt;
    stack<int>sta;
    void Init()
    {
        G.clear();
        G.resize(n+1);
        Time = cnt = 0;
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(du, 0, sizeof(du));
        memset(f, 0, sizeof(f));
        memset(Is, 0, sizeof(Is));
    }
    
    void Tarjan(int u, int father)
    {
        f[u] = father;
        dfn[u] = low[u] = ++Time;
        int len = G[u].size(), v, k=0;
        sta.push(u);
        Is[u] = 1;
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
            if(v == father && !k)
            {
                k++;
                continue;
            }
            if(!dfn[v])
            {
                Tarjan(v, u);
                low[u] = min(low[u], low[v]);
            }
            else
            {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u])
        {
            do
            {
                v = sta.top();
                Is[v] = 0;
                sta.pop();
                block[v] = cnt;
            }while(u!=v);
            cnt++;
        }
    }
    
    int main()
    {
        int a, b;
        while(scanf("%d %d", &n, &m)!=EOF)
        {
            Init();
            while(m--)
            {
                scanf("%d %d", &a, &b);
                G[a].push_back(b);
                G[b].push_back(a);
            }
            for(int i=1; i<=n; i++)
                if(!dfn[i])
                    Tarjan(i,-1);
            for(int i=1; i<=n; i++)
            {
                int v = f[i];
                if(v == -1)
                {
                    continue;
                }
                if(block[i] != block[v])
                {
                    du[block[i] ]++;
                    du[block[v] ]++;
                }
            }
            int ans = 0;
            for(int i=0; i<cnt; i++)
            {
                if(du[i]==1)
                    ans++;
            }
            printf("%d
    ",(ans+1)/2);
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    网络流
    KMP算法
    光现象
    物理学习须知
    声现象
    常见物理量测量方法
    洛谷 P1373 小a和uim之大逃离
    洛谷 P1242 新汉诺塔
    电磁现象
    磁化
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4713353.html
Copyright © 2011-2022 走看看