zoukankan      html  css  js  c++  java
  • BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量

    BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量

    Description

    煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

    Input

    输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖       S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。

    Output

    输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。

    Sample Input

    9
    1 3
    4 1
    3 5
    1 2
    2 6
    1 5
    6 3
    1 6
    3 2
    6
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    0

    Sample Output

    Case 1: 2 4
    Case 2: 4 1

    HINT

    Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
    Case 2 的一组解为(4,5,6,7)。

    缩点双(扩点双?)
    需要注意入栈的是边,以及根节点度数为1的情况。
    对于本题,只需要考虑坍塌在割点的情况。
    考虑缩点双之后的每个点,如果仅有一个割点相邻,说明是叶子,则需要设一个。
    如果整个图只有一个点双,一共只需要设两个。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 100050
    typedef long long ll;
    vector<int>V[N];
    int head[N],to[N<<1],nxt[N<<1],cnt=1;
    int vis[N<<1],S[N<<1],top,bl[N<<1],bcc,dfn[N],low[N],rt,tot,iscut[N],fa[N],n,m;
    inline void add(int u,int v) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    void dfs(int x) {
        int i,num=0;
        dfn[x]=low[x]=++tot;
        for(i=head[x];i;i=nxt[i]) {
            if(vis[i]) continue;
            vis[i]=vis[i^1]=1;
            num++;
            S[++top]=i;
            if(!dfn[to[i]]) {
                dfs(to[i]);
                low[x]=min(low[x],low[to[i]]);
                if(dfn[x]<=low[to[i]]) {
                    iscut[x]=1;
                    int t;
                    ++bcc; V[bcc].clear();
                    do {
                        t=S[top--];
                        int u=to[t^1],v=to[t];
                        if(fa[u]!=bcc) fa[u]=bcc,V[bcc].push_back(u);
                        if(fa[v]!=bcc) fa[v]=bcc,V[bcc].push_back(v);
                    }while(t!=i);
                }
            }else {
                low[x]=min(low[x],dfn[to[i]]);
            }
        }
        if(rt==x&&num<2) iscut[x]=0;
    }
    int Cas;
    void solve() {
        n=0;
        Cas++;
        memset(head,0,sizeof(head)); cnt=1;
        memset(iscut,0,sizeof(iscut));
        memset(dfn,0,sizeof(dfn));
        memset(fa,0,sizeof(fa));
        memset(vis,0,sizeof(vis));
        top=0; bcc=0;
        int i,x,y,j;
        for(i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x),n=max(n,max(x,y));
        for(i=1;i<=n;i++) {
            if(!dfn[i]) {
                dfs(rt=i);
            }
        }
        int ans1=0; ll ans2=1;
        // for(i=1;i<=n;i++) printf("%d
    ",iscut[i]);
        // printf("%d
    ",bcc);
        for(i=1;i<=bcc;i++) {
            int lim=V[i].size(),num=0;
            for(j=0;j<lim;j++) {
                // printf("%d
    ",V[i][j]);
                if(iscut[V[i][j]]) num++;
            }
            // puts("FUCK");
            if(num==1) ans1++,ans2=ans2*(lim-1);
        }
        if(bcc==1) ans1=2,ans2=1ll*(V[1].size()-1)*(V[1].size())/2;
        printf("Case %d: %d %lld
    ",Cas,ans1,ans2);
    }
    int main() {
        while(scanf("%d",&m)!=EOF&&m) solve();
    }
    
  • 相关阅读:
    目标检测算法的总结(R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD、FNP、ALEXnet、RetianNet、VGG Net-16)
    目标检测评价标准(mAP, 精准度(Precision), 召回率(Recall), 准确率(Accuracy),交除并(IoU))
    JavaScript中继承的多种方式和优缺点
    使用Vue封装暂无数据占位图组件
    Vue组件间通信方式到底有几种
    通俗易懂了解Vue中nextTick的内部实现原理
    从0开始编写webpack插件
    常用的webpack优化方法
    通俗易懂了解Vue内置组件keep-alive内部原理
    原生JS实现集合结构
  • 原文地址:https://www.cnblogs.com/suika/p/9279183.html
Copyright © 2011-2022 走看看