• 计蒜客 商业信息共享


    有 N 个公司,从每个公司都能单向地向另外一个公司分享最新商业信息,因为他们之间有着某种合作,你需要解决两个问题:

    1. 现在有一个最新的商业信息,至少需要告诉多少个公司,使得所有的公司最终都能得到该信息。
    2. 在原有基础上,至少需要再让多少对公司建立这种合作,使任意一个公司获得某个最新商业信息后,经过若干次分享,所有的公司最终都能得到该信息。

    输入格式

    第一行输入一个整数 N (1N100)。

    接下来 N行,每行若干个整数,表示第 ii 个公司可以向哪些公司分享信息,以 0 结束。

    输出格式

    输出共两行,每行一个整数,分别表示问题 1 和问题 2 的答案。

    样例输入

    6
    0
    6 0
    2 0
    2 0
    3 1 0
    0

    样例输出

    2
    2
    分析:先缩点,第一小问就是求有多少点的入度为0,第二小问怎么求呢?
    显然要加边使原图变成一个强联通分量,一定要让图中的所有点的出度和入度都为0,每次我们可以连一条边从出度为0的到入度为0的,但是可能出度入度为0的点数量不相等,取个max就好了.
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    
    using namespace std;
    
    int n, ru[110], chu[110], head[110], nextt[10000], to[10000], tot = 1, scc[110], num, dfs_clock, pre[110], low[110],map[110][110];
    int ru1[110], chu1[110];
    
    stack<int> s;
    
    void add(int x, int y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void tarjan(int u)
    {
        pre[u] = low[u] = ++dfs_clock;
        s.push(u);
        for (int i = head[u]; i; i = nextt[i])
        {
            int v = to[i];
            if (!pre[v])
            {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else
                if (!scc[v])
                    low[u] = min(low[u], pre[v]);
        }
        if (low[u] == pre[u])
        {
            num++;
            while (1)
            {
                int t = s.top();
                s.pop();
                scc[t] = num;
                if (t == u)
                    break;
            }
        }
    }
    
    void lianbian(int x)
    {
        for (int i = head[x]; i; i = nextt[i])
        {
            int v = to[i];
            if (scc[x] != scc[v] && !map[scc[x]][scc[v]])
            {
                map[scc[x]][scc[v]] = 1;
                chu1[scc[x]]++;
                ru1[scc[v]]++;
            }
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            int x;
            while (scanf("%d", &x) && x != 0)
            {
                add(i, x);
                ru[x]++;
                chu[i]++;
            }
        }
        for (int i = 1; i <= n; i++)
            if (!scc[i])
                tarjan(i);
        for (int i = 1; i <= n; i++)
            lianbian(i);
        int ans = 0,rucnt = 0,chucnt = 0;
        for (int i = 1; i <= num; i++)
        {
            if (!ru1[i])
                ans++;
        }
        printf("%d
    ", ans);
        //printf("%d
    ", num);
        int cr = 0, cc = 0;
        for (int i = 1; i <= n; i++)
        {
            if (chu[i] == 0)
                cc++;
            if (ru[i] == 0)
                cr++;
        }
        printf("%d", max(cc, cr));
    
        return 0;
    }
     
  • 相关阅读:
    用sp_change_users_login消除Sql Server的孤立用户
    数据库连接字符串大全
    系统登录的设计与研究
    DB2常用命令大全(转)
    哈希表(HashTable)探究(转)
    转: C#实现的18位身份证格式验证算法
    通过SQLNET.ora文件限制Ip地址访问(转)
    AS/400(iSeries)
    使用Asp.Net构建安全网站
    DB2备份命名(转)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7522403.html
Copyright © 2020-2023  润新知