zoukankan      html  css  js  c++  java
  • 【luogu P2002】消息扩散

    https://www.luogu.org/problem/show?pid=2002

    SCC缩点的模板题,缩点后统计入度为0的点的数量就完了。

    #include <iostream>
    #include <vector>
    #include <stack>
    #include <cstring>
    #define maxn 100005
    using namespace std;
    int n, m;
    vector<int> g[maxn], g2[maxn];
    int indegree[maxn];
    
    int timer = 0, cnter = 0;
    int dfn[maxn], low[maxn], scc[maxn];
    stack<int> sta;
    bool insta[maxn];
    void dfs(int v)
    {
        /*
        low[v]=min{
            dfn[v],
            low[w], 存在有向边(v,w)且搜索到v时w尚未被搜索到
            dfn[w]  存在有向边(v,w)且搜索到v时w在栈内
        }
        */
        low[v] = dfn[v] = ++timer;
        sta.push(v);
        insta[v] = true;
        for (int i = 0; i < g[v].size(); i++)
        {
            int w = g[v][i];
            if (!dfn[w])
            {
                dfs(w);
                low[v] = min(low[v], low[w]);
            }
            else if (insta[w])
            {
                low[v] = min(low[v], dfn[w]);
            }
        }
        if (dfn[v] == low[v])
        {
            ++cnter;
            int t;
            do
            {
                t = sta.top();
                sta.pop();
                insta[t] = false;
                scc[t] = cnter;
            } while (t != v);
        }
    }
    void tarjan_scc()
    {
        for (int i = 1; i <= n; i++)
        {
            if (!dfn[i])
                dfs(i);
        }
    }
    void contract()
    {
        for (int v = 1; v <= n; v++)
        {
            for (int i = 0; i < g[v].size(); i++)
            {
                // 对于边(v,w),若v与w不在同一SCC,则该边在缩点后的新图为(scc[v],scc[w])
                int w = g[v][i];
                if (scc[v] != scc[w])
                {
                    g2[scc[v]].push_back(scc[w]);
                    indegree[scc[w]]++;
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        int u, v;
        for (int i = 1; i <= m; i++)
        {
            cin >> u >> v;
            g[u].push_back(v);
        }
        tarjan_scc();
        contract();
    
        // 统计得到的DAG中入度为0的点
        int ans = 0;
        for (int i = 1; i <= cnter; i++)
        {
            if (!indegree[i])
                ans++;
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    Validate US Telephone Numbers
    7月份总结
    Arguments Optional
    Everything Be True
    手机开发网页模板(20140124)
    整站开发初始化
    switch滑动开关
    js 面向对象
    Bootstrap 导航栏
    Bootstrap 标签页
  • 原文地址:https://www.cnblogs.com/ssttkkl/p/7531377.html
Copyright © 2011-2022 走看看