• A


    题意:学校有一些单向网络,现在需要传一些文件,1,求最少需要向几个学校分发文件才能让每个学校都收到,2,需要添加几条网络才能在任意一个学校分发都可以传遍所有学校。
    分析:首先应该求出来连通分量,进行缩点,然后求每个分量的入度和出度,入度等于0的很明显都需要分发一个文件,至于需要添加几条边可以成为一个强连通,就是出度和入度最大的那个,因为需要把出度和入度相连。
    ****************************************************************
    #include<stdio.h>
    #include<string.h>
    #include<stack>
    #include<algorithm>
    using namespace std;

    const int MAXN = 105;

    ///邻接表变量
    struct Edge{int v, next;}e[MAXN*MAXN];
    int Head[MAXN], cnt;

    void AddEdge(int u, int v)
    {
        e[cnt].v = v;
        e[cnt].next = Head[u];
        Head[u] = cnt++;
    }

    ///tarjan算法变量
    int sta[MAXN], inStack[MAXN], top;
    int dfn[MAXN], low[MAXN], index;
    int belong[MAXN], bnt;

    void tarjan(int k)
    {
        int j;

        dfn[k] = low[k] = ++index;
        inStack[k] = true;
        sta[++top] = k;

        for(j=Head[k]; j!=-1; j=e[j].next)
        {
            int v = e[j].v;
            if( !dfn[v] )
            {
                tarjan(v);
                low[k] = min(low[k], low[v]);
            }
            else if(inStack[v])
                low[k] = min(low[k], dfn[v]);
        }

        if(dfn[k] == low[k])
        {
            ++bnt;
            do
            {
                j = sta[top--];
                inStack[j] = false;
                belong[j] = bnt;
            }
            while(k != j);
        }
    }
    void InIt(int N)
    {
        cnt = bnt = index = 0;
        top = 0;

        for(int i=1; i<=N; i++)
        {
            Head[i] = -1;
            dfn[i] = false;
        }
    }

    int main()
    {
        int N;

        while(scanf("%d", &N) != EOF)
        {
            int i, j, u, v;

            InIt(N);

            for(i=1; i<=N; i++)
            {
                while(scanf("%d", &v), v)
                    AddEdge(i, v);
            }

            for(i=1; i<=N; i++)if(!dfn[i])
                tarjan(i);

            int r[MAXN]={0}, c[MAXN]={0}, rn=0, cn=0;

            for(i=1; i<=N; i++)
            for(j=Head[i]; j!=-1; j=e[j].next)
            {
                u = belong[i], v = belong[e[j].v];
                if(u != v)
                {
                    c[u]++;
                    r[v]++;
                }
            }

            for(i=1; i<=bnt; i++)
            {
                if(r[i] == 0)rn++;
                if(c[i] == 0)cn++;
            }

            if(bnt == 1)
                printf("1 0 ");
            else
                printf("%d %d ", rn, max(rn, cn));
        }

        return 0; 

    }

     



  • 相关阅读:
    BZOJ1443 [JSOI2009]游戏Game
    BZOJ4950 [Wf2017]Mission Improbable
    假期编程
    假期编程
    假期编程
    假期编程
    假期编程练习-求和
    假期编程练习——一个数的n次幂取余
    假期编程练习———十进制转二进制
    小球抛物线运动
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4691257.html
Copyright © 2020-2023  润新知