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

    原题链接

    • 题解:考虑容斥,即假设是有向的完全图,那么边的数量必然是 (n imes(n-1)),考虑并不是强连通图,那么最接近的情况即是两个强连通分量,考虑如何形成,那么就是在原图缩完点的基础上,保留一个入度或者出度为零的(我就是没想到还有可能是出度为零)强连通分量不与除了自己以外的任何强连通分量连线,那么就是 (min imes (n-min))
    • 代码:
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <queue>
    #include <map>
    using namespace std;
    typedef long long ll;
    const int N = 200100;
    const int M = 4000010;
    int h[M], ne[M], to[M], idx;
    int dfn[N], low[N], times;
    int stk[N], instk[N], top;
    int scc_cnt, sz[N], id[N];
    int d[N],d2[N];
    int U[N], V[N];
    void add(int u, int v) {ne[idx] = h[u], to[idx] = v, h[u] = idx++;}
    void tarjan(int u) {
        dfn[u] = low[u] = ++times;
        stk[++top] = u;instk[u] = 1;
        for (int i = h[u]; ~i ;i = ne[i]) {
            int v = to[i];
            if (!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if (instk[v]) low[u]=min(low[u], dfn[v]);
        }
        if (low[u] == dfn[u]) {
            scc_cnt++;
            while (1) {
                int v = stk[top];
                instk[v] = 0;
                sz[scc_cnt]++;
                id[v] = scc_cnt;
                top--;
                if (v == u) break;
            }
        }
    }
    void init() {
        memset(h, -1, sizeof h);
        idx = scc_cnt = times   = top = 0;
        memset(dfn, 0, sizeof dfn);
        memset(sz, 0, sizeof sz);
        memset(d, 0, sizeof d);
        memset(d2, 0, sizeof d2);
    }
    int cas = 0;
    void solve() {
        ll n, m;scanf("%lld%lld", &n, &m);
        init();
        for (int i = 1; i <= m; i ++) {
            int u, v;
            scanf("%d%d",  &u, &v);
            U[i]= u, V[i] = v;
            add(u, v);
        }
        for (int i = 1; i <= n; i ++) {
            if (!dfn[i])tarjan(i);
        }
        memset(h, -1, sizeof h);
        for (int i = 1; i <= m; i ++) {
            int uu = id[U[i]];
            int vv = id[V[i]];
            if (uu == vv)continue;
            add(uu, vv);
            d[uu] ++;
            d2[vv]++;
        }
        ll ans = 99999999999999;
        ll Min1 = ans, Min2 = ans;
        for (int i = 1; i <= scc_cnt; i ++) {
            if (d[i] == 0) {
                Min1 = min(Min1, sz[i]*1ll);
            }if (d2[i] == 0) {
                Min1 = min(Min1, sz[i] * 1ll);
            }
        }
        ans = n * (n-1) - m - ((n-Min1) * Min1);
        printf("Case %d: %lld
    ", ++cas, (scc_cnt == 1?-1:ans) );
    }
    int main() {
        int t = 1;scanf("%d", &t);//cin >> t;
        while (t--)solve();
        return 0;
    }
    
  • 相关阅读:
    使用springamqp发送消息及同步接收消息
    对未登陆的用户进行处理的页面
    查找某些字符是否在另一个字符串里出现的高效算法
    正则表达式
    华中地区高校第七届ACM程序设计大赛——递增序列【2012年5月27日】
    HDOJ2021 ( 发工资咯:) ) 【水题】
    循环冗余校验(CRC)【C语言 位运算】
    HDOJ2028 ( Lowest Common Multiple Plus ) 【水题,lcm】
    HDOJ2015 ( 偶数求和 ) 【水题】
    HDOJ2027 ( 统计元音 ) 【水题】
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14634588.html
Copyright © 2011-2022 走看看