POJ 1236 Network of Schools(强连通分量)

来源:互联网 发布:网络机顶盒电视直播软件下载 编辑:程序博客网 时间:2024/06/05 11:27

题目分析

这道题首先强连通处理 ,然后求缩点之后的每个点的入度和出度。第一个肯定就是输出入度为0的点,第二个就是输出入度和出度的最大值,因此要保证一个图强连通,那么这个图的每个点肯定既有出去的边也有进来的边。注意当整个图相连通的时候的时候要特判。

#include <stack>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1005;int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;vector <int> G[maxn];stack <int> S;int in[maxn], out[maxn];int dfs(int u){    pre[u] = lowlink[u] = ++dfs_clock;    S.push(u);    for(unsigned int i = 0; i < G[u].size(); i++){        int v = G[u][i];        if(!pre[v]){            dfs(v);            lowlink[u] = min(lowlink[u], lowlink[v]);        }        else if(!sccno[v]){            lowlink[u] = min(lowlink[u], pre[v]);        }    }    if(lowlink[u] == pre[u]){        scc_cnt++;        for(;;){            int x = S.top(); S.pop();            sccno[x] = scc_cnt;            if(x == u) break;        }    }    return lowlink[u];}void find_scc(int n){    dfs_clock = scc_cnt = 0;    memset(in, 0, sizeof(in));    memset(out, 0, sizeof(out));    memset(pre, 0, sizeof(pre));    memset(lowlink, 0, sizeof(lowlink));    memset(sccno, 0, sizeof(sccno));    for(int i = 0; i < n; i++)        if(!pre[i]) dfs(i);}int main(){    int n;    while(scanf("%d", &n) != EOF){        int v;        for(int u = 0; u < n; u++){            while(scanf("%d", &v) && v){                v--;                G[u].push_back(v);            }        }        find_scc(n);        for(int u = 0; u < n; u++){            for(unsigned int i = 0; i < G[u].size(); i++){                int v = G[u][i];                if(sccno[v] != sccno[u]) in[sccno[v]] = out[sccno[u]] = 1;            }        }        int a = 0, b = 0;        for(int i = 1; i <= scc_cnt; i++){            if(!in[i]) a++;            if(!out[i]) b++;        }        if(scc_cnt == 1) printf("1\n0\n");        else printf("%d\n%d\n", a, max(a,b));    }    return 0;}
0 0