zoukankan      html  css  js  c++  java
  • UVA-10972 RevolC FaeLoN (边双连通+缩点)

    题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边。

    题目分析:所谓强连通,就是无向图中任意两点可互达。找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需考虑在bcc图上加有向边。如果,bcc图是由v个孤立的点,0条边构成的,则最少需要添加v条(将v个点首尾顺次连起来构成一条圈)有向边。如果由v个点,k条边构成,则对于每一个顶点,如果度数大于2,就不用给它加任何边,因为它一定能会在圈中;如果度数为1,则为这个点添只加一条边即可;如果度数为0,也就是孤立点,要想连在圈中,必须添加两条边。最后,考虑到重复,把累加和除以2后向上取整便是答案。

    找边双连通分量套模板。。。标记每一个桥,再深搜一次,过程中不经过桥。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<vector>
    # include<stack>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define REP(i,s,n) for(int i=s;i<n;++i)
    # define CL(a,b) memset(a,b,sizeof(a))
    
    struct Edge
    {
        int to,flag;
        Edge(int v,int f):to(v),flag(f){}
    };
    const int N=1005;
    int n,m,bcc_cnt,dfs_clock,low[N],pre[N],bccno[N],du[N];
    vector<int>G[N];
    vector<Edge>e;
    
    void dfs(int u,int fa)
    {
        low[u]=pre[u]=++dfs_clock;
        REP(i,0,G[u].size()){
            int v=e[G[u][i]].to;
            if(!pre[v]){
                dfs(v,u);
                low[u]=min(low[v],low[u]);
                if(low[v]>low[u])
                    e[G[u][i]].flag=e[G[u][i]^1].flag=1;
            }else if(pre[v]<pre[u]&&v!=fa)
                low[u]=min(low[u],pre[v]);
        }
    }
    
    void dfs1(int u)
    {
        bccno[u]=bcc_cnt;
        REP(i,0,G[u].size()){
            int v=e[G[u][i]].to;
            if(!bccno[v]&&!e[G[u][i]].flag) dfs1(v);
        }
    }
    
    void findBcc()
    {
        CL(bccno,0);
        CL(pre,0);
        dfs_clock=bcc_cnt=0;
        REP(i,0,n) if(!pre[i]) dfs(i,-1);
        REP(i,0,n) if(!bccno[i]){
            ++bcc_cnt;
            dfs1(i);
        }
    }
    
    int main()
    {
        int a,b;
        while(~scanf("%d%d",&n,&m))
        {
            e.clear();
            REP(i,0,n) G[i].clear();
            while(m--)
            {
                scanf("%d%d",&a,&b);
                --a,--b;
                e.push_back(Edge(b,0));
                e.push_back(Edge(a,0));
                G[a].push_back(e.size()-2);
                G[b].push_back(e.size()-1);
            }
            findBcc();
            if(bcc_cnt==1){
                printf("0
    ");
                continue;
            }
            CL(du,0);
            REP(u,0,n){
                REP(i,0,G[u].size()){
                    int v=e[G[u][i]].to;
                    if(bccno[u]!=bccno[v])  ++du[bccno[v]];
                }
            }
            int ans=0;
            REP(i,1,bcc_cnt+1){
                if(du[i]==1) ++ans;
                if(du[i]==0) ans+=2;
            }
            printf("%d
    ",(ans+1)/2);
        }
        return 0;
    }
    

      

  • 相关阅读:
    flutter 布局
    常见错误
    xpath
    bzoj1485 [HNOI2009]有趣的数列 卡特兰数
    博弈 Nim问题 POJ2234
    bzoj 1014 [JSOI2008]火星人prefix
    codevs 1743 反转卡片 rope or splay
    bzoj 2326 矩阵乘法
    bzoj 1702 贪心,前缀和
    bzoj 1700 Problem Solving 解题 dp
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4924463.html
Copyright © 2011-2022 走看看