zoukankan      html  css  js  c++  java
  • HDU 4635 Strongly connected

    题目大意:

    给你N个顶点,M条边的有向图,问最多加入多少条边之后,这个图仍旧是一个简单图(简单图:无重边,无自环),
    并且不是强联通的。如果原始的图就是强联通的话就输出 -1.
     
    1.找出强联通块,计算每个连通块内的点数。将点数最少的那个连通块单独拿出来,其余的连通块合并成一个连通分量。 那么假设第一个连通块的 点数是 x  第二个连通块的点数是 y, 已经有的边数是 m 则
    ans =  x*(x-1) + y*(y-1) + x*y - m;(强联通块内边数最多是 n*(n-1) ),  
     
    这里最少点数的强联通分量要满足一个条件,就是出度或者入度为 0才行,不然是不满足的。
     
    
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    usingnamespace std;
    #define INF 0x7ffffff
    #define maxn 100005
    typedef longlong LL;
    #define Min(a,b) (a<b?a:b)
    int low[maxn], dfn[maxn], Time, m, n,  belong[maxn];
    int Stack[maxn], top, blocks, sum[maxn], InDegree[maxn], OutDegree[maxn];
    bool InStack[maxn];
    vector<vector<int> > G;
    void init()
    {
        memset(InDegree, 0, sizeof(InDegree));
        memset(OutDegree, 0, sizeof(OutDegree));
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(InStack, false, sizeof(InStack));
        memset(belong, 0, sizeof(belong));
        memset(sum, 0, sizeof(sum));
        blocks = Time = top = 0;
        G.clear();
        G.resize(n+2);
    }
    void Tarjan(int u)
    {
        low[u] = dfn[u] = ++Time;
        Stack[top++] = u;
        InStack[u] = true;
        int len = G[u].size(), v;
    
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
    
            if( !low[v] )
            {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            elseif( InStack[v] )
                low[u] = min(low[u], dfn[v]);
        }
    
        if(low[u] == dfn[u])
        {
            do
            {
                v = Stack[--top];
                belong[v] = blocks;
                InStack[v] = false;
                sum[blocks] ++;
            }while(u != v);
            blocks ++;
        }
    }
    void solve()
    {
        for(int i=1; i<=n; i++)
        {
            if( !low[i] )
                Tarjan(i);
        }
        for(int i=0; i<=n; i++)
        {
            int len = G[i].size(), v;
            for(int j=0; j<len; j++)
            {
                v = G[i][j];
                int a = belong[i], b = belong[v];
                if(a != b)
                {
                    OutDegree[a] ++;
                     InDegree[b] ++;
                }
            }
        }
        LL x = INF, y;
        for(int i=0; i<blocks; i++)
        {
            if( !OutDegree[i] || !InDegree[i])
                x = Min(x, sum[i]);
        }
        y = n - x;
        LL ans = x*(x-1) + y*(y-1) + x*y - m;
    
        if(blocks == 1)
            printf("-1
    ");
        else
            printf("%lld
    ", ans);
    
    }
    int main()
    {
        int T, cas = 1;
        scanf("%d", &T);
    
        while(T--)
        {
            scanf("%d %d",&n, &m);
            init();
            for(int i=0; i<m; i++)
            {
                int a, b;
                scanf("%d %d", &a, &b);
                G[a].push_back(b);
            }
            printf("Case %d: ", cas ++);
            solve();
        }
        return0;
    }
  • 相关阅读:
    判断touchmove上下的方向
    this的指向
    JS 判断浏览器是否安装Flash 兼容IE、firefox
    Array类型
    addEventListener()与removeEventListener()
    tap 点透问题
    ts 接口
    ts 类型断言
    ts学习
    vue时间戳转换(10位数)/(13位)
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4718746.html
Copyright © 2011-2022 走看看