zoukankan      html  css  js  c++  java
  • HDU 4635 —— Strongly connected——————【 强连通、最多加多少边仍不强连通】

    Strongly connected
    Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

    Description

    Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a simple directed graph. Also, after you add these edges, this graph must NOT be strongly connected. 
    A simple directed graph is a directed graph having no multiple edges or graph loops.
    A strongly connected digraph is a directed graph in which it is possible to reach any node starting from any other node by traversing edges in the direction(s) in which they point. 
     

    Input

    The first line of date is an integer T, which is the number of the text cases. 
    Then T cases follow, each case starts of two numbers N and M, 1<=N<=100000, 1<=M<=100000, representing the number of nodes and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is a edge from x to y.
     

    Output

    For each case, you should output the maximum number of the edges you can add. 
    If the original graph is strongly connected, just output -1.
     

    Sample Input

    3
    3 3
    1 2
     
    2 3
    3 1
    3 3
    1 2
    2 3
    1 3
    6 6
    1 2
    2 3
    3 1
    4 5
    5 6
    6 4
     

    Sample Output

    Case 1: -1
    Case 2: 1
    Case 3: 15
     
     
    题目大意:给n个结点,m条有向边。问你最多加多少条边,让原图仍然不是强连通的。如果图本身就是强连通的,输出-1
     
    解题思路:如果要让图不是强连通图,那么必须会将分成两部分。我们设左部分为X,右部分为Y。X这边的结点个数设为x,X这边的结点个数设为y,想要加边最多,那么可以让左边X成为完全图,右边Y成为完全图。让X与Y之间全部都是一个方向的边,即如果是X--->Y的,那么所有都是从X->Y的;如果是从Y--->X的,那么所有都是Y->X的。那么我们可以得到一个公式计算这样能形成的所有边数  F = x*y + x*(x-1) + y*(y-1)表示X与Y之间形成的边数+X形成完全图的边数+Y形成完全图的边数。x+y = n。公式可以进一步化简得:F = n*n - n - (xy)。这是总的边数。那么如果想让F越大,那么只要x*y值越小即可。当x+y 为定值时,x*y的值越小,则需要x与y的差值越大。那么我们通过缩点以后,让缩点出度或者入度为0的单独放在X或者Y,让剩余的放到另一侧。然后通过枚举这样的缩点,即可找到结果。
     
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<string.h>
    #include<vector>
    using namespace std;
    typedef long long INT;
    const int maxn = 100100;
    struct Edge{
        int from,to,dist,next;
        Edge(){}
        Edge(int _to,int _next):to(_to),next(_next){}
    }edges[maxn];
    int tot, head[maxn];
    void init(){
        tot = 0;
        memset(head,-1,sizeof(head));
    }
    void AddEdge(int _u,int _v){
        edges[tot] = Edge(_v,head[_u]);
        head[_u] = tot++;
    }
    int dfs_clock, scc_cnt;
    int sccno[maxn], dfn[maxn], lowlink[maxn];
    stack<int>S;
    void dfs(int u){
        lowlink[u] = dfn[u] = ++dfs_clock;
        S.push(u);
        for(int i = head[u]; i != -1; i = edges[i].next){
            int v = edges[i].to;
            if(!dfn[v]){
                dfs(v);
                lowlink[u] = min(lowlink[u], lowlink[v]);
            }else if(!sccno[v]){
                lowlink[u] = min(lowlink[u],dfn[v]);
            }
        }
        if(lowlink[u] == dfn[u]){
            scc_cnt++;
            for(;;){
                int x = S.top();
                S.pop();
                sccno[x] = scc_cnt;
                if(x == u){
                    break;
                }
            }
        }
    }
    void find_scc(int n){
        dfs_clock = scc_cnt = 0;
        memset(sccno,0,sizeof(sccno));
        memset(dfn,0,sizeof(dfn));
        for(int i = 1; i <= n; i++){
            if(!dfn[i]){
                dfs(i);
            }
        }
    }
    int outdeg[maxn], indeg[maxn];
    INT sccsz[maxn];
    int main(){
        int T, m, cas = 0;
        INT n;
        scanf("%d",&T);
        while(T--){
            scanf("%lld%d",&n,&m);
            init();
            int a,b;
            for(int i = 0; i < m; i++){
                scanf("%d%d",&a,&b);
                AddEdge(a,b);
            }
            find_scc(n);
            printf("Case %d: ",++cas);
            if(scc_cnt == 1){
                puts("-1");continue;
            }
            memset(indeg,0,sizeof(indeg));
            memset(outdeg,0,sizeof(outdeg));
            memset(sccsz,0,sizeof(sccsz));
            for(int i = 1; i <= n; i++){
                sccsz[sccno[i]]++;
                for(int j = head[i]; j != -1; j = edges[j].next){
                    int v = edges[j].to;
                    if(sccno[i] == sccno[v]){
                        continue;
                    }
                    indeg[sccno[v]]++;
                    outdeg[sccno[i]]++;
                }
            }
            INT ans = 0;
            for(int i = 1; i <= scc_cnt; i++){
                if(indeg[i] == 0 ||outdeg[i] == 0){
                    ans = max( ans, (n*n - n - sccsz[i]*(n - sccsz[i]))-m );
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    /*
    555
    7 9
    1 5
    1 2
    5 6
    6 7
    7 5
    6 4
    2 4
    4 3
    3 2
    
    */
    

      

     
  • 相关阅读:
    JavaScript 事件
    Docker 部署asp.netcore
    Docker 安装
    JavaScript 窗口操作
    JavaScript 定时器
    JavaScript Dom
    Javascript try catch es5标准模式
    JavaScript 数组去重
    JavaScript 返回具体类型方法
    mysql 触发器
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4943453.html
Copyright © 2011-2022 走看看