• Network of Schools---poj1236(强连通分量)


    题目链接

    题意:学校有一些单向网络,现在需要传一些文件

    求:1,求最少需要向几个学校分发文件才能让每个学校都收到,

      2,需要添加几条网络才能从任意一个学校分发都可以传遍所有学校。

    解题思路(参考大神的):

    —        1. 求出所有强连通分量

    —        2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。

    —        3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少

    在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少

    加边的方法:

    要为每个入度为0的点添加入边,为每个出度为0的点添加出边

    假定有 n 个入度为0的点,m个出度为0的点,如何加边?

    把所有入度为0的点编号 0,1,2,3,4 ....N -1

    每次为一个编号为i的入度0点可达的出度0点,添加一条出边,连到编号为(i+1)%N 的那个出度0点,

    这需要加n条边

    若 m <= n,则

    加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边

    若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。

    所以,max(m,n)就是第二个问题的解

    此外:当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0;

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #include <stack>
    using namespace std;
    #define INF 0xfffffff
    #define N 10060
    int Out[N],In[N], n;
    
    int low[N], dfn[N], num, cnt, Time, vis[N], belong[N];
    vector<int> G[N];
    stack<int>sta;
    
    void Init()
    {
        Time=num=cnt=0;
        for(int i=0;i<=n;i++)
            G[i].clear();
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(vis, 0, sizeof(vis));
        memset(belong, 0, sizeof(belong));
        memset(Out, 0, sizeof(Out));
        memset(In, 0, sizeof(In));
    }
    
    void Tarjan(int u)
    {
        dfn[u] = low[u] = ++Time;
        int len = G[u].size(), v;
        sta.push(u);
        vis[u] = 1;
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
            if(dfn[v]==0)
            {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if(vis[v]==1)
            {
                low[u] = min(dfn[v], low[u]);
            }
        }
        if(low[u]==dfn[u])
        {
            ++num;
            do
            {
                v = sta.top();
                belong[v] = num;// 缩点;
                sta.pop();
                vis[v] = 0;
            }while(u!=v);
        }
    }
    int main()
    {
        int a, ans1, ans2, ans, u, v;
        while(scanf("%d", &n)!=EOF)
        {
            Init();
    
            for(int i=1; i<=n; i++)
            {
                while(scanf("%d", &a), a)
                {
                    G[i].push_back(a);
                }
            }
            for(int i=1; i<=n; i++)
                if(!dfn[i])
                    Tarjan(i);
            ans1 = ans2 = 0;
            for(int i=1; i<=n; i++)
            {
                int len=G[i].size();
                for(int j=0; j<len; j++)
                {
                    u = belong[i]; v = belong[G[i][j]];
                    if(u!=v)
                    {
                        Out[u]++;
                        In[v]++;
                    }
                }
            }
            for(int i=1; i<=num; i++)
            {
                if(Out[i]==0)ans2++;
                if(In[i]==0)ans1++;
            }
            ans = max(ans1, ans2);
            if(num==1)
                printf("1
    0
    ");
            else
                printf("%d
    %d
    ", ans1, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    创建FLASK,同步docker
    FLASK Buleprint
    restful api
    Angular JS
    线程日志
    将项目部署到linux下的docker容器中
    安装和卸载docker
    学习目录总编
    Ansible
    装饰器
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4708365.html
Copyright © 2020-2023  润新知