zoukankan      html  css  js  c++  java
  • POJ1236 Network of Schools (强连通)(缩点)

                                                                Network of Schools
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 16343   Accepted: 6484

    Description

    A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B
    You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.

    Input

    The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line.

    Output

    Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B.

    Sample Input

    5
    2 4 3 0
    4 5 0
    0
    0
    1 0
    

    Sample Output

    1
    2
    【分析】第一问就是问最少有多少个连通块,可以用Tarjan缩点,然后看入度为0的连通分量有多少个就行了。
    第二问就是问最少添加几条边使得这个无向图变成一个连通块,缩点后,令father为树根数,令son为子叶数,则答案为max(father,son),若缩点后就一个点,则输出1 0。
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #define inf 0x3f3f3f3f
    #define mod 10000
    typedef long long ll;
    using namespace std;
    const int N=105;
    const int M=10005;
    int s,t,n,m,cnt,tim,top,cut;
    int head[N],dfn[N],low[N],stack1[N];
    int num[N],in[N],out[N],vis[N];
    bool flag=false;
    struct man
    {
        int to,nxt;
    }edg[M];
    void addedg(int u,int v)
    {
        edg[cnt].to=v;edg[cnt].nxt=head[u];head[u]=cnt++;
    }
    void init()
    {
        cnt=0;tim=1;top=cut=0;
        memset(head,-1,sizeof head);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(stack1,0,sizeof stack1);
        memset(num,0,sizeof num);
        memset(in,0,sizeof in);
        memset(out,0,sizeof out);
        memset(vis,0,sizeof vis);
        memset(edg,0,sizeof edg);
    }
    void dfs(int u) {
        int v;
        low[u] = dfn[u] = ++tim;
        stack1[top++] = u;
        vis[u] = 1;
        for(int e = head[u]; e != -1; e = edg[e].nxt)
        {
            v = edg[e].to;
            if(!dfn[v])
            {
                dfs(v);
                low[u] = min(low[u], low[v]);
            }
            else if(vis[v])
            {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(low[u] == dfn[u])
        {
            cut++;//printf("!!!%d ",u);
            do
            {
                v = stack1[--top];
                num[v] = cut;
                vis[v] = 0;
            }while(u != v);
        }
    }
    int main() {
        while(~scanf("%d",&n)){
        init();
        for(int i=1;i<=n;i++){
            while(1){
                scanf("%d",&m);
                if(!m)break;
                addedg(i,m);
            }
        }
        for(int i=1;i<=n;i++)if(!dfn[i])dfs(i);
        for(int i=1;i<=n;i++){
            for(int j=head[i];j!=-1;j=edg[j].nxt){
                int v=edg[j].to;//printf("%d %d %d %d ",i,num[i],v,num[v]);
                if(num[i]!=num[v])out[num[i]]++,in[num[v]]++;
            }
        }
        int father=0,son=0;
        for(int i=1;i<=cut;i++){
            if(in[i]==0)father++;
            if(out[i]==0)son++;
        }
        if(cut==1)printf("1 0 ");
        else printf("%d %d ",father,max(father,son));
        }
        return 0;
    }

  • 相关阅读:
    Account group in ERP and its mapping relationship with CRM partner group
    错误消息Number not in interval XXX when downloading
    错误消息Form of address 0001 not designated for organization
    Algorithm类介绍(core)
    梯度下降与随机梯度下降
    反思
    绘图: matplotlib核心剖析
    ORB
    SIFT
    Harris角点
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/5890134.html
Copyright © 2011-2022 走看看