• uva5135


    题意是给你一个无向图,让你求至少要放多少个太平井,使得图中任意一个点坏掉,在其它所有点的人都能通过安全井逃生。

    显然先求出BCC(点双)。

    显然把井放在割顶不合适,因为如果割顶挂了,这个放在割顶的井不能帮助任何人逃生。

    然后对于一个BCC,如果它只有一个割顶,那么一定要在非割顶处放一口井,因为如果割顶挂了,剩下的人就和大部队分离开来,他们需要一口井,这口井放在BCC中除了割顶的任意一个点都可以。

    如果一个BCC有两个割顶,那么就无关紧要了。因为题目中说,最多只会有一个点被破坏,所以如果有两个割顶的话,一个坏了,剩下的人还可以通过另一个跑掉。

    所以做法就是跑一遍tarjan求出所有的BCC,然后对于只有一个割顶的BCC,要在BCC中除了割顶的任意一点放置一口井,对于两个或以上的,不用放井。

    BCC中若无割顶,则说明整个图是个BCC。

    否则BCC中一定有一个割顶。(这句话可以换一个表述,两个BCC之间一定是由割顶相连,如果没有割顶相连,则这两个BCC可以合并为一个割顶)

    最后乘法原理一波带走。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <vector>
    #define LL long long
    
    using namespace std;
    
    const LL maxn = 5 * 1e4 + 5, maxm = maxn * 2;
    
    LL N, n, tot, dfs_clock, bcc_cnt, ans1, ans2;
    
    LL h[maxn], low[maxn], dfn[maxn], bccno[maxn], iscut[maxn];
    
    struct edge
    {
        LL v, next;
    }a[maxm];
    
    struct EDGE
    {
        LL u, v;
    };
    
    vector<LL> bcc[maxn];
    
    stack<EDGE> s;
    
    void add(LL x, LL y)
    {
        a[tot].v = y;
        a[tot].next = h[x];
        h[x] = tot++;
    }
    
    LL dfs(LL u, LL fa)
    {
        LL lowu = dfn[u] = ++dfs_clock;
        LL child = 0;
        for (LL i = h[u]; ~i; i = a[i].next)
        {
            LL v = a[i].v;
            EDGE e = (EDGE){u, v}; 
            if (!dfn[v])
            {
                s.push(e);
                child++;
                LL lowv = dfs(v, u);
                lowu = min(lowu, lowv);
                if (lowv >= dfn[u])
                {
                    iscut[u] = 1;
                    bcc_cnt++;
                    bcc[bcc_cnt].clear();
                    for(;;)
                    {
                        EDGE x = s.top(); s.pop();
                        if (bccno[x.u] != bcc_cnt)
                        {
                            bcc[bcc_cnt].push_back(x.u);
                            bccno[x.u] = bcc_cnt;
                        }if (bccno[x.v] != bcc_cnt)
                        {
                            bcc[bcc_cnt].push_back(x.v);
                            bccno[x.v] = bcc_cnt;
                        }
                        if (x.u == u && x.v == v) break;
                    }
                }
            }
            else if (dfn[v] < dfn[u] && v != fa)
                {
                    s.push(e);
                    lowu = min(lowu ,dfn[v]);
                }
        }
        if (fa == 0 && child == 1)
        {
            iscut[u] = 0;
        }
        return low[u] = lowu;
    } 
    
    int main()
    {
    //    freopen("uva5135.in","r",stdin);
        LL kase = 0;
        while (scanf("%lld", &N) && N)
        {
            memset(h, -1, sizeof h); tot = bcc_cnt = dfs_clock = 0;
            memset(iscut, 0, sizeof iscut);
            memset(dfn, 0, sizeof dfn);
            memset(low, 0, sizeof low);
            memset(bccno, 0, sizeof bccno);
            LL n = 0;
            for (LL i = 1; i <= N; i++)
            {
                LL x, y;
                scanf("%lld%lld", &x, &y);
                add(x, y); add(y, x);
                n = max(n, max(x, y));
            }
            dfs(1, 0);
            
            ans1 = 0; ans2 = 1;
            if (bcc_cnt == 1)
            {
                ans1 = 2; ans2 = n * (n - 1) / 2;
            }else
            for (LL i = 1; i <= bcc_cnt; i++)
            {
                LL cut_cnt = 0;
                for (LL j = 0; j < bcc[i].size(); j++)
                    if (iscut[bcc[i][j]])
                        cut_cnt++;
                if (cut_cnt == 1)
                {
                    ans1++; ans2 *= bcc[i].size() - 1;
                }
            }
            printf("Case %lld: %lld %lld
    ", ++kase, ans1, ans2);
        }
        return 0;
    }

    还有一个做法是先找出割顶,然后从非割顶的点开始dfs,dfs的过程中不许经过割顶。稍后补坑。

  • 相关阅读:
    java 递归函数
    iOS安全攻防(三):使用Reveal分析他人app
    mapreduce任务失败、重试、猜測式运行机制小结
    javascript UniqueID属性
    弧度和角度的转换
    批处理批量创建90个用户
    【设计模式】状态模式
    【.NET进程通信】初探.NET中进程间通信的简单的实现
    天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,增益其所不能
    冷门却使用的 javascript 技巧
  • 原文地址:https://www.cnblogs.com/yohanlong/p/7771588.html
Copyright © 2020-2023  润新知