zoukankan      html  css  js  c++  java
  • CF505D Mr. Kitayuta's Technology

    CF505D Mr. Kitayuta's Technology

    一道结论题。

    (M) 个询问中提及的点数为 (cnt), 记这些点按照询问形成图的联通块个数为 (K),第 (i) 个联通块大小为 (siz_i)

    对于每个联通块,容易发现边数不是 (siz_i-1) 就是 (siz_i) 那么什么时候是(siz_i-1) 呢,是这个联通块不含强连通分量的时候。反之为 (siz_i),这个可以手动验证。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <stack>
    
    using namespace std;
    
    typedef int ll;
    const ll MAXN = 1e6+10;
    
    stack <ll> st;
    vector <ll> g[MAXN], g2[MAXN];
    ll N, M, fa[MAXN], siz[MAXN], has[MAXN], num, dfn[MAXN], low[MAXN], vis[MAXN];
    ll bel[MAXN], _N, tag1[MAXN], tag2[MAXN];
    
    ll find_(ll);
    void tarjan(ll);
    
    int main() {
        scanf("%d%d", &N, &M);
        for (ll i = 1, x, y; i <= M; i++) {
            scanf("%d%d", &x, &y);
            tag1[x] = tag1[y] = 1;
            g[x].push_back(y);
        }
        for (ll i = 1; i <= N; i++) if (!dfn[i]) tarjan(i);
        for (ll i = 1; i <= N; i++) {
            for (unsigned int j = 0; j < g[i].size(); j++) {
                ll v = g[i][j];
                if (bel[v] != bel[i]) g2[bel[i]].push_back(bel[v]);
                else has[bel[i]] = 1;
            }
            if (tag1[i]) tag2[bel[i]] = 1;
        }
        for (ll i = 1; i <= _N; i++)
            sort(g2[i].begin(), g2[i].end()), g2[i].erase(unique(g2[i].begin(), g2[i].end()), g2[i].end());
        for (ll i = 1; i <= _N; i++) fa[i] = i;
        for (ll i = 1; i <= _N; i++) {
            for (unsigned int j = 0; j < g2[i].size(); j++) {
                ll fx = find_(i), fy = find_(g2[i][j]);
                if (fx != fy) {
                    fa[fx] = fy;
                    has[fy] |= has[fx];
                    siz[fy] += siz[fx];
                }
            }
        }
        ll ans = 0;
        for (ll i = 1; i <= _N; i++) {
            if (find_(i) == i && tag2[i]) {
                ans += siz[i] - 1 + has[i];
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    void tarjan(ll n) {
        dfn[n] = low[n] = ++num;
        st.push(n);
        for (unsigned int i = 0; i < g[n].size(); i++) {
            ll v = g[n][i];
            if (vis[v]) continue;
            if (dfn[v]) low[n] = min(low[n], dfn[v]);
            else {
                tarjan(v);
                low[n] = min(low[n], low[v]);
            }
        }
        if (dfn[n] == low[n]) {
            ll t;
            _N++;
            do {
                t = st.top();
                st.pop();
                bel[t] = _N;
                vis[t] = 1;
                siz[_N] += tag1[t];
            } while (n != t);
        }
    }
    
    ll find_(ll x) {return fa[x] == x ? x : fa[x] = find_(fa[x]);}
    
  • 相关阅读:
    mysql关联查询
    文本框,下拉框,单选框只读状态属性
    sql索引实例
    sql视图实例
    SQL触发器实例
    存储过程实例
    sql 、linq、lambda 查询语句的区别
    LINQ中的一些查询语句格式
    面试宝典
    SQL常用语句
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13904529.html
Copyright © 2011-2022 走看看