• 【poj2553】The Bottom of a Graph(强连通分量缩点)


    题目链接:http://poj.org/problem?id=2553

    【题意】

    给n个点m条边构成一幅图,求出所有的sink点并按顺序输出。sink点是指该点能到达的点反过来又能回到该点。

    【思路】

    不难想象sink点一定是在强连通分量中,而且强连通分量缩点后出度为0,就可以说明该强连通分量内所有的点都是sink点。

    之前wa了一发是因为写成了out[i],注意是从缩点构成的dag中找出度为0的点,而不是从原来的图中找。

    【ac代码】

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int N = 5005;
    int low[N], vis[N], dfn[N], col[N], out[N], ans[N];
    vector<int>V[N];
    stack<int>s;
    int n, cnt, num;
    void dfs(int u)
    {
        s.push(u);
        vis[u] = 1;
        dfn[u] = low[u] = ++cnt;
        for (int i = 0; i < V[u].size(); i++)
        {
            int v = V[u][i];
            if (!dfn[v])
            {
                dfs(v);
                low[u] = min(low[u], low[v]);
            }
            else if (vis[v])
                low[u] = min(low[u], dfn[v]);
        }
        if (low[u] == dfn[u])
        {
            int t;
            num++;
            do
            {
                t = s.top();
                s.pop();
                col[t] = num;
                vis[t] = 0;
            }
            while (t != u);
        }
    }
    
    void tarjan()
    {
        int i;
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(vis, 0, sizeof(vis));
        memset(col, 0, sizeof(col));
        while (!s.empty()) s.pop();
        cnt = num = 0;
        for (i = 1; i <= n; i++)
            if (!dfn[i]) dfs(i);
    }
    int main()
    {
        int m, i, j;
        while(scanf("%d", &n), n)
        {
            scanf("%d", &m);
            for(i = 1; i <= n; i++) V[i].clear();
            int a, b;
            while(m--)
            {
                scanf("%d%d", &a, &b);
                V[a].push_back(b);
            }
            tarjan();
            memset(out, 0, sizeof out);
            for(i = 1; i <= n; i++)
                for(j = 0; j < V[i].size(); j++)
                {
                    int v = V[i][j];
                    if(col[i] != col[v]) out[col[i]]++;//该颜色出度+1
                }
            cnt = 0;
            for(i = 1; i <= n; i++)
                if(!out[col[i]]) ans[++cnt] = i;
            sort(ans+1, ans+1+cnt);
            for(i = 1; i < cnt; i++) printf("%d ", ans[i]);
            printf("%d
    ", ans[cnt]);
        }
        return 0;
    }
  • 相关阅读:
    boost::asio::error的用法浅析
    boost::asio::buffer
    sqlserver2008安装图解
    WCF 聊天室程序代码详细讲解教程
    C#中使用Property Grid(属性面板)控件
    TXT>Access 使用DAO数据源!(VB Code)
    读取INI文件 VbCode
    Pet Shop 4
    模式行为型
    C#编程规范
  • 原文地址:https://www.cnblogs.com/lesroad/p/8460630.html
Copyright © 2020-2023  润新知