zoukankan      html  css  js  c++  java
  • 洛谷

    https://www.luogu.org/problem/P3225

    这个东西有点绕。

    最平凡的情况,整个原图只有一个点,那么它坍塌了之后就没有点了,不需要进行任何逃生。否则,当一个点坍塌之后,每个其他点的工人都要逃向逃生出口。

    首先把双连通分量缩点,缩点完成之后必定是一片森林,树与树之间是乘法原理。

    单独考虑一棵树。

    平凡的情况,只有一个根节点,没有边。

    这种情况下,假如原图中该双连通分量中有>=2个点,则这个双连通分量中要建立2个出口(其中一个出口坍塌了,都可以从另一个出口走),否则假如只有一个点,则只需要建立1个出口。

    不平凡的情况,是一棵无根树。必定存在叶子,每个叶子都必须建立1个出口。这个出口必须建立在非原图割点的位置,假如原图这个双连通分量没有割点(这个双连通分量只有一个点,去掉都没没事),则不需要加。

    不是叶子的情况,当其他节点坍塌,则必定可以去到至少1个叶子节点逃生,不需要建立逃生出口。当自己(且自己只有一个点)坍塌,每个子树自己跑去自己的叶子就可以了。

    那么先特判掉n=1的情况。然后在原图中跑出原图的割点。然后遍历一遍原图的点,从没有被访问过的非割点进入,搜索连接的所有非割点,这些非割点都属于这个双连通分量,而搜索到的割点也属于这个双连通分量不过不需要进去。这样会漏掉两个割点之间的所有非割点和割点,不过这貌似没有问题?因为假如都有两个非割点了,答案就是0了。而且环的另一个半(或者1/3,或者1/4)也会搜索到那两个割点的,反正都是0。

    假如只有一个割点,则这个是缩点后图的叶子,贡献C(非割点数量,1)。

    假如有多于两个割点,则不贡献,少数的非割点和割点都无所谓了

    假如没有割点,则这个双连通分量缩点之后只剩下自己一个点作为树,那么也是贡献C(非割点数量,2),(当该双连通分量有多于两个点时),或者0(当该双连通分量只有1个点时)。

    各个双连通分量之间选点独立,各个树之间选点独立,全部乘法叠加。

    从这道题可以得到一个常识:每个割点不一定仅属于一个双连通分量,比如一个dio型图。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 505;
    
    int n;
    vector<int> G[MAXN];
    
    int dfn[MAXN], low[MAXN], dfncnt;
    bool cut[MAXN];
    int vis[MAXN], viscol;
    int cntcut, cntncut;
    
    void init() {
        for(int i = 1; i <= 500; ++i)
            G[i].clear();
        dfncnt = 0;
        memset(cut, false, sizeof(cut));
        memset(vis, false, sizeof(vis));
        memset(dfn, false, sizeof(dfn));
        memset(low, false, sizeof(low));
        viscol = 1;
    }
    
    
    void tarjan(int u, int p) {
        low[u] = dfn[u] = ++dfncnt;
        ll sum = 0;
        int ch = 0;
        for(auto v : G[u]) {
            if(!dfn[v]) {
                tarjan(v, u);
                low[u] = min(low[u], low[v]);
                if(p == -1)
                    ch++;
                else if(low[v] >= dfn[u])
                    cut[u] = true;
            } else
                low[u] = min(low[u], dfn[v]);
        }
        if(ch >= 2)
            cut[u] = true;
    }
    
    void dfs(int u, int p) {
        //cout << "u=" << u << endl;
        vis[u] = viscol;
        ++cntncut;
        for(auto v : G[u]) {
            if(vis[v] != viscol) {
                vis[v] = viscol;
                if(cut[v])
                    ++cntcut;
                else
                    dfs(v, u);
            }
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int m, kase = 1;
        while(~scanf("%d", &m)) {
            if(m == 0)
                return 0;
            init();
            n = 0;
            for(int i = 1, u, v; i <= m; ++i) {
                scanf("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
                n = max(n, max(u, v));
            }
            for(int i = 1; i <= n; ++i) {
                if(!dfn[i])
                    tarjan(i, -1);
                /*if(cut[i])
                    printf("cut=%d
    ",i);*/
            }
            unsigned long long sum1 = 0;
            unsigned long long sum2 = 1;
            for(int i = 1; i <= n; ++i) {
                if(!vis[i]  && !cut[i]) {
                    //cout<<"viscol="<<viscol<<endl;
                    cntcut = cntncut = 0;
                    dfs(i, -1);
                    if(cntcut == 0) {
                        if(cntncut >= 2) {
                            sum1 += 2;
                            sum2 *= cntncut * (cntncut - 1) / 2;
                        } else {
                            sum1 += 1;
                        }
                    } else if(cntcut == 1) {
                        ++sum1;
                        sum2 *= cntncut;
                    } else
                        ;
                    viscol++;
                }
            }
            printf("Case %d: %llu %llu
    ", kase++, sum1, sum2);
        }
        return 0;
    }
    
  • 相关阅读:
    SQLAlchemy介绍
    Flask介绍
    逆转的生殖——形而下的EOE补完仪式…
    huiyin
    实验课上
    我的博客今天1岁213天了,我领取了…
    关于直接写屏
    OceanBorn&nbsp;&nbsp;歌曲列表
    Gethsemane
    光辉岁月-Beyond
  • 原文地址:https://www.cnblogs.com/Yinku/p/11363294.html
Copyright © 2011-2022 走看看