zoukankan      html  css  js  c++  java
  • BZOJ 2730 矿场搭建

    割点

    割点以外的点坍塌不影响其他人逃生,因为假设我们任取两个个非割点s建立救援站,非割点的任意点坍塌,我们都可以从割点走到一个救援出口。

    所以我们只考虑割点坍塌的情况。

    我们可以先找出图中所有的割点。

    假如图中没有割点,那么肯定需要两个救援出口才能保证有路走。

    假如有割点,对于每个不含割点的联通块,若该联通块只与一个割点相连,那么则需要选择该联通块中的一个点建立救援出口;若该联通块与两个以上割点相连,那么这块联通块里则不需要建立救援出口。

    数据范围很小,随便搞搞!

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 1000;
    int n, m, cnt, k, root, tot, c, head[N], dfn[N], low[N], scc[N], rd[N];
    bool vis[N], cut[N];
    struct Edge { int v, next; } edge[N<<2];
    
    void addEdge(int a, int b){
        edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
    }
    
    void init(){
        full(head, -1), full(cut, false), full(dfn, 0), full(low, 0);
        full(scc, 0), full(rd, 0);
        cnt = 0, tot = 0, k = 0, n = 0;
    }
    
    void tarjan(int s){
        dfn[s] = low[s] = ++k;
        int flag = 0;
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(!dfn[u]){
                tarjan(u);
                low[s] = min(low[s], low[u]);
                if(low[u] >= dfn[s]){
                    flag ++;
                    if(s != root || flag > 1) cut[s] = true;
                }
            }
            else low[s] = min(low[s], dfn[u]);
        }
    }
    
    void dfs(int s){
        vis[s] = true;
        if(!scc[s]) scc[s] = tot;
        else scc[s] = -1;
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(!vis[u] && !cut[u]) dfs(u);
        }
    }
    
    int main(){
    
        while(~scanf("%d", &m) && m){
            init();
            for(int i = 0; i < m; i ++){
                int s = read(), t = read();
                addEdge(s, t), addEdge(t, s);
                n = max(s, t, n);
            }
            for(int i = 1; i <= n; i ++){
                if(!dfn[i]) root = i, tarjan(i);
            }
            for(int s = 1; s <= n; s ++){
                if(cut[s]){
                    full(vis, false);
                    for(int i = head[s]; i != -1; i = edge[i].next){
                        int u = edge[i].v;
                        if(!cut[u] && !vis[u]) tot ++, dfs(u);
                    }
                }
            }
            for(int i = 1; i <= n; i ++){
                if(scc[i] != -1) rd[scc[i]] ++;
            }
            int p = 0; ll tmp = 1;
            for(int i = 1; i <= tot; i ++){
                if(rd[i]) p ++, tmp *= rd[i];
            }
            if(!p) printf("Case %d: 2 %lld
    ", ++c, (ll)(n * (n - 1) / 2));
            else printf("Case %d: %d %lld
    ", ++c, p, tmp);
        }
        return 0;
    }
    
  • 相关阅读:
    PHP面试总结
    yii2-dingtalk 钉钉群机器人
    分布式锁机制原理及实现方式
    strtotime的一个使用问题
    JavaScript的程序构成
    libsvm源码凝视+算法描写叙述:svm_train
    android事件分发(二)
    Windows 上通过本地搭建 Jekyll环境
    重点:用户画像
    easyui英文提示变中文
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10787592.html
Copyright © 2011-2022 走看看