zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    NOIP2011 D1T1 铺地毯
    NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并
    POJ 2513 trie树+并查集判断无向图的欧拉路
    599. Minimum Index Sum of Two Lists
    594. Longest Harmonious Subsequence
    575. Distribute Candies
    554. Brick Wall
    535. Encode and Decode TinyURL(rand and srand)
    525. Contiguous Array
    500. Keyboard Row
  • 原文地址:https://www.cnblogs.com/staginner/p/3364075.html
Copyright © 2011-2022 走看看