• HDU 3844 Mining Your Own Business


        首先,如果图本来就是一个点双联通的(即不存在割点),那么从这个图中选出任意两个点就OK了。

        如果这个图存在割点,那么我们把割点拿掉后图就会变得支离破碎了。对于那种只和一个割点相连的块,这个块中至少要选一个点出来建逃生通道,而且可以任意选择,而对于那种和多个割点相连的块则没必要选点出来建逃生通道。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 100010
    #define MAXM 100010
    #pragma comment(linker, "/STACK:102400000,102400000")
    typedef long long LL;
    int dfn[MAXN], low[MAXN], h[MAXN], ind;
    bool vis[MAXN];
    int N, M, first[MAXN], e, next[MAXM], v[MAXM], col[MAXN];
    struct Edge
    {
        int x, y;
    }edge[MAXM];
    void dfs(int u, int p, int o)
    {
        dfn[u] = low[u] = ++ ind;
        int cnt = 0;
        for(int i = first[u]; i != -1; i = next[i])
        {
            if(v[i] == p) continue;
            if(!dfn[v[i]])
            {
                ++ cnt;
                dfs(v[i], u, o);
                low[u] = std::min(low[u], low[v[i]]);
                if(u == o && cnt > 1) h[u] = 1;
                else if(u != o && low[v[i]] >= dfn[u]) h[u] = 1;
            }
            else low[u] = std::min(low[u], dfn[v[i]]);
        }
    }
    void tarjan()
    {
        for(int i = 1; i <= N; i ++)
            low[i] = dfn[i] = h[i] = 0;
        ind = 0;
        dfs(i, -1, i);
    }
    void add(int x, int y)
    {
        v[e] = y;
        next[e] = first[x], first[x] = e ++;
    }
    void input()
    {
        N = 0;
        for(int i = 0; i < M; i ++)
        {
            scanf("%d%d", &edge[i].x, &edge[i].y);
            N = std::max(edge[i].x, N);
            N = std::max(edge[i].y, N);
        }
        memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0;
        for(int i = 0; i < M; i ++)
            add(edge[i].x, edge[i].y), add(edge[i].y, edge[i].x);
    }
    void find(int x, int c, int &pn, int &cn)
    {
        vis[x] = true, ++ pn;
        for(int i = first[x]; i != -1; i = next[i])
        {
            int y = v[i];
            if(vis[y]) continue;
            if(h[y])
            {
                if(col[y] != c) col[y] = c, ++ cn;
                continue;
            }
            find(y, c, pn, cn);
        }
    }
    void process()
    {
        tarjan();
        memset(vis, 0, sizeof(vis[0]) * (N + 1));
        memset(col, 0, sizeof(col[0]) * (N + 1));
        LL ans = 1;
        int cnt = 0;
        for(int i = 1; i <= N; i ++)
            if(!h[i] && !vis[i])
            {
                int pn = 0, cn = 0;
                find(i, i, pn, cn);
                if(cn == 0) ans *= (LL)pn * (pn - 1) / 2, cnt += 2;
                else if(cn == 1) ans *= pn, ++ cnt;
            }
        printf("%d %I64d
    ", cnt, ans);
    }
    int main()
    {
        int t = 0;
        while(scanf("%d", &M), M > 0)
        {
            input();
            printf("Case %d: ", ++ t);
            process();
        }
        return 0;
    }
  • 相关阅读:
    获取redis指定实例中所有的key
    gtid环境下mysqldump对于set-gtid-purged的取值
    统计redis大key信息(前topN)
    通过otter元数据表获取有用的信息
    另外一种获取redis cluster主从关系和slot分布的方法
    直观获取redis cluster 主从关系
    MongoDB 分片篇
    练习Mongodb 复制集篇
    堆和栈
    原码、反码、补码
  • 原文地址:https://www.cnblogs.com/staginner/p/3364075.html
Copyright © 2020-2023  润新知