zoukankan      html  css  js  c++  java
  • [强联通分量_DFS] 0725

    N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。
    问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
    问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

    input format:
    输入有多组样例,大约1000组。
    每组样例第一行包含两个整数N,M(2<=N<=100),N代表学校的个数,M代表边的个数(M<N*N)
    接下来M行,每行包含连个整数u,v,代表u可以向v单向发送数据。

    output format
    每组样例对应两行,分别是问题一和问题二的解。

    sample input
    7 8
    1 2
    2 3
    3 1
    1 4
    4 5
    5 6
    6 4
    7 6

    sample output
    2
    2

    ----------------------------------------------------------------------------------

    所需发放软件的数量为缩点后入度为0的点的个数,所需添加的边为入度为0和出度为0点的个数的较大者。

    ----------------------------------------------------------------------------------

    # include <cstdio>
    # include <cstring>
    
    # define N 100 + 5
    
    int n, m;
    int t, cols;
    int f[N], c[N], in[N], out[N];
    char vis[N], g[N][N];
    
    void read_graph(void)
    {
        int u, v;
        for (int i = 1; i <= n; ++i)
        {
            in[i] = 0;
            memset(g[i]+1, 0, sizeof(int)*n);
        }
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d%d", &u, &v);
            g[u][v] = 1;
        }
    }
    
    void dfs(int u)
    {
        vis[u] = 1;
        for (int v = 1; v <= n; ++v) if (!vis[v] && g[u][v])
            dfs(v);
        f[++t] = u;
    }
    
    void rdfs(int u)
    {
        vis[u] = 1;
        c[u] = cols;
        for (int v = 1; v <= n; ++v) if (!vis[v] && g[v][u])
            rdfs(v);
    }
    
    void solve(void)
    {
        t = 0;
        memset(vis+1, 0, sizeof(char)*n);
        for (int i = 1; i <= n; ++i) if (!vis[i]) dfs(i);
        cols = 0;
        memset(vis+1, 0, sizeof(char)*n);
        for (int i = n; i >= 1; --i) if (!vis[f[i]]) ++cols, rdfs(f[i]);
        if (cols == 1) {printf("1\n0\n"); return ;}
        memset(in+1,  0, sizeof(int)*cols);
        memset(out+1, 0, sizeof(int)*cols);
        for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
        {
            if(g[i][j] && c[i] != c[j])
            {
                ++in[c[j]];
                ++out[c[i]];
            }
        }
        int zin = 0, zout = 0;
        for (int i = 1; i <= cols; ++i)
        {
            if (in[i]  == 0) ++zin;
            if (out[i] == 0) ++zout;
        }
        printf("%d\n%d\n", zin, zin>zout ? zin:zout);
    }
    
    
    int main()
    {    
        while (~scanf("%d%d", &n, &m))
        {
            read_graph();
            solve();
        }
        
        return 0;
    }
  • 相关阅读:
    网游开发中的可怕群体:单机派
    关卡设计的基本理论
    游戏程序员所需的知识体系
    关于SQL Server将一列的多行内容拼接成一行的问题讨论——之一(转)
    c# lmada 修改List内容
    c# 取sqlite库分组的第一行不对
    关于SQL Server将一列的多行内容拼接成一行的问题讨论(转)
    “打包的”爱情
    “婚礼哥”隔空喊爱:我要做你一生的北京情人
    北漂,都不敢奢望爱情?
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2626079.html
Copyright © 2011-2022 走看看