zoukankan      html  css  js  c++  java
  • POJ 2553 The Bottom of a Graph(强连通分量的出度)

    题意:

    求出图中所有汇点

    定义:点v是汇点须满足 --- 对图中任意点u,若v可以到达u则必有u到v的路径;若v不可以到达u,则u到v的路径可有可无。

    模板:http://www.cnblogs.com/Jadon97/p/8328750.html

     

    分析:

    很显然, 图中强连通分量中所有的点属性都是一样的, 要么都是汇点, 要么都不是。

    如果有一个强连通分量A的边连向强连通分量B, 那么A一定不是汇点, 因为B不会有边连向A(如果有的话A、B就是同一个强连通分量了)。

     求出所有强连通分量, 然后再求一下出度即可

    #include <stack>
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int maxn = 5678;
    vector<int> G[maxn];
    int n , m;
    int dfn[maxn], low[maxn], color[maxn], out_degree[maxn];
    int dfs_num = 1, col_num = 1;
    bool vis[maxn];//标记元素是否在栈中
    stack<int> s;
    void Tarjan(int u)
    {
        dfn[ u ] = dfs_num;
        low[ u ] = dfs_num++;
        vis[u] = true; //标记访问
        s.push(u); // 入栈
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if( ! dfn[v])
            {
                Tarjan( v );
                low[u] = min(low[v], low[u]);
            }
            else if(vis[v]) //如果在v栈中 , 更新low[u]
            {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u])
        {
            vis[u] = false;
            color[u] = col_num;
            int t;
            for(;;){
                int t = s.top(); s.pop();
                color[t] = col_num;
                vis[t] = false;
                if(t == u) break;
            }
            col_num++;
        }
    }
    int main()
    {
        while(~scanf("%d %d", &n,&m))
        {
            if(n == 0) break;
            for(int i = 0; i < maxn; i++) G[i].clear();
            memset(dfn, 0 , sizeof(dfn));
            memset(vis, 0 , sizeof(vis));
            memset(low, 0 , sizeof(low));
            memset(color, 0, sizeof(color));
            memset( out_degree, 0 ,sizeof(out_degree));
            dfs_num = 1, col_num = 1;
            for(int i = 0; i < m; i++)
            {
                int u , v;
                scanf("%d %d", &u, &v);
                G[u].push_back(v);
            }
    
            for(int i = 1; i <= n; i++){
                if(!dfn[i])
                    Tarjan(i);
            }
    
    
            for(int u = 1; u <= n; u++){ //
                for(int i = 0; i <  G[u].size(); i++){//枚举每一条边
                    int v = G[u][i];
                    if(color[u] != color[v]){ //如果有一条u到v的边, 但u,v不是同一个强连通分量, 说明u所在的强连通分量有一条出边指向v, u中都不是题目所求
                        out_degree[color[u]]++;
                    }
                }
            }
    
            int cnt = 0, ans[maxn];
            for(int u = 1; u <= n; u++){
                if(out_degree[color[u]] == 0) ans[cnt++] = u;
            }
            printf("%d",ans[0]);
            for(int i = 1;i < cnt; i++) printf(" %d", ans[i]); puts("");
        }
        return 0;
    }
  • 相关阅读:
    ES6变量的解构赋值
    ES6新增内容
    Rvalue references
    range-based for statement
    Space in Template Expression, nullptr, and auto
    Type Alias、noexcept、override、final
    Variadic Template
    =default =delete
    为什么不要特化函数模版?
    boost::noncopyable 的作用
  • 原文地址:https://www.cnblogs.com/Jadon97/p/8328880.html
Copyright © 2011-2022 走看看