zoukankan      html  css  js  c++  java
  • BZOJ2438: [中山市选2011]杀人游戏(tarjan)

    题意

    题目链接

    Sol

    这题挺考验阅读理解能力的。。

    如果能读懂的话,不难发现这就是在统计有多少入度为(0)的点

    缩点后判断一下即可

    当然有一种例外情况是(1 -> 3, 2 -> 3),也就是存在一个孤立点,判掉即可

    判断的时候应当满足三个条件:所在联通块大小为(2),入度为0,所有指向的点入度均大于(2)

    另外就是题目中没有说有没有重边,我没判过了,但是最好还是判一下。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e6 + 10;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, M;
    vector<int> v[MAXN];//let's have a test
    int dfn[MAXN], low[MAXN], vis[MAXN], tot, col[MAXN], cn, inder[MAXN], ans, siz[MAXN], flag[MAXN];
    stack<int> s;
    void tarjan(int x) {
        dfn[x] = low[x] = ++tot; vis[x] = 1; s.push(x);
        vector<int> *e = &v[x];
        for(int i = 0, to; i < e -> size(); i++) {
            if(!dfn[to = (*e)[i]]) tarjan(to), low[x] = min(low[x], low[to]);
            else if(vis[to]) low[x] = min(low[x], dfn[to]);
        }
        if(low[x] == dfn[x]) {
            int h; ++cn;
            do {
                h = s.top(); s.pop(); vis[h] = 0; col[h] = cn; siz[cn]++;
            }while(h != x);
        }
    }
    void rebuild() {
        for(int i = 1; i <= N; i++) {
            vector<int> *e = &v[i];
            for(int j = 0, to; j < e -> size(); j++) 
                if(col[i] != col[to = (*e)[j]]) 
                    inder[col[to]]++;		
        } 
        for(int i = 1; i <= cn; i++) if(!inder[i]) ans++;
    }
    int main() {
        N = read(); M = read();
        for(int i = 1; i <= M; i++) {
            int x = read(), y = read();
            v[x].push_back(y);
        }
        for(int i = 1; i <= N; i++) if(!dfn[i]) tarjan(i);
        rebuild();
        for(int i = 1; i <= N; i++) {
            if((!inder[col[i]]) && siz[col[i]] == 1) {
                bool flag = 0; vector<int> *e = &v[i];
                for(int j = 0, to; j < e -> size(); j++) {
                    if(inder[col[to = (*e)[j]]] == 1)
                        {flag = 1; break;}
                }
                if(flag == 0) {printf("%.6lf", 1 - (double) (ans - 1) / N); return 0;}
            }
        }
        printf("%.6lf", 1 - (double) ans / N);
        return 0;
    }
    /*
    7 8
    4 5
    5 4
    4 2
    1 2
    1 3
    6 3
    6 7
    7 6
    */
    
    
  • 相关阅读:
    上市前为什么要分红
    在文件开始追加一行
    c++ 日期时间工具
    windows c++找不到time.h sys/types.h
    截取ls -l的某一列
    提取指定类型文件到指定目录,保留目录结构
    批量转换当前目录下的文件名为snake case
    vcpkg boost uuid Bcrypt 链接问题
    文件名pascal转underscore
    vcpkg cmake 找不到boost
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9828222.html
Copyright © 2011-2022 走看看