POJ1236 Network of Schools 【强连通分量Garbow】

Network of Schools

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 11180   Accepted: 4448

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

题意:给定各台电脑的连接情况,求两个问题:1、最少向网络中的几台电脑投放文件,则整个网络中的所有电脑能立刻获得该文件;2、最少要向网络中添加几条单向连接可以使得这个网络中只要投放一份文件到任意一台电脑,则所有电脑都能获得该文件。

题解:第一道Garbow题,需要注意的地方是当给定图是连通图时不需要添加任何边。

改进后的一个版本:0ms

#include <stdio.h>
#include <string.h>
#define maxn 102
#define maxm maxn * maxn

int head[maxn], sta1[maxn], sta2[maxn], scc[maxn];
int low[maxn], id, id1, id2, sec, sccNum;
bool in[maxn], out[maxn];
struct Node{
    int to, next;
} E[maxm];

void addEdge(int u, int v)
{
    E[id].to = v;
    E[id].next = head[u];
    head[u] = id++;
}

void getMap(int n)
{
    memset(head, -1, sizeof(int) * (n + 1));
    int i, v; id = 0;
    for(i = 1; i <= n; ++i)
        while(scanf("%d", &v), v)
            addEdge(i, v);
}

void Garbow(int pos)
{
    sta1[id1++] = sta2[id2++] = pos;
    low[pos] = ++sec;
    for(int i = head[pos]; i != -1; i = E[i].next){
        if(!low[E[i].to]) Garbow(E[i].to);
        else if(!scc[E[i].to])
            while(low[E[i].to] < low[sta2[id2-1]]) --id2;
        if(scc[E[i].to]) in[scc[E[i].to]] = 1;
    }
    if(sta2[id2-1] == pos){
        ++sccNum; --id2; int v;
        do{
            v = sta1[--id1];
            scc[v] = sccNum;
        } while(sta1[id1] != pos);
    }
}

void solve(int n)
{
    memset(low, 0, sizeof(int) * (n + 1));
    memset(scc, 0, sizeof(int) * (n + 1));
    memset(in, 0, sizeof(bool) * (n + 1));
    memset(out, 0, sizeof(bool) * (n + 1));
    int i, j, ans1 = 0, ans2 = 0; id1 = id2 = sec = sccNum = 0;
    for(i = 1; i <= n; ++i)
        if(!low[i]) Garbow(i);
    for(i = 1; i <= n; ++i)
        for(j = head[i]; j != -1; j = E[j].next)
            if(scc[i] != scc[E[j].to]){
                out[scc[i]] = 1; break;
            }
    if(sccNum != 1){
        for(i = 1; i <= sccNum; ++i){
            if(!out[i]) ++ans2;
            if(!in[i]) ++ans1;
        }
        if(ans1 > ans2) ans2 = ans1;
    }else ans1 = 1;
    printf("%d\n%d\n", ans1, ans2);
}

int main()
{
    int n;
    while(scanf("%d", &n) == 1){
        getMap(n);
        solve(n);
    }
    return 0;
}

原32ms:

#include <stdio.h>
#include <string.h>
#define maxn 102
#define maxm maxn * maxn

int head[maxn], sta1[maxn], sta2[maxn], scc[maxn];
int low[maxn], id, id1, id2, sec, sccNum;
bool in[maxn], out[maxn];
struct Node{
    int to, next;
} E[maxm];

void addEdge(int u, int v)
{
    E[id].to = v;
    E[id].next = head[u];
    head[u] = id++;
}

void getMap(int n)
{
    memset(head, -1, sizeof(int) * (n + 1));
    int i, v; id = 0;
    for(i = 1; i <= n; ++i)
        while(scanf("%d", &v), v)
            addEdge(i, v);
}

void Garbow(int pos)
{
    sta1[id1++] = sta2[id2++] = pos;
    low[pos] = ++sec;
    for(int i = head[pos]; i != -1; i = E[i].next)
        if(!low[E[i].to]) Garbow(E[i].to);
        else if(!scc[E[i].to])
            while(low[E[i].to] < low[sta2[id2-1]]) --id2;
    if(sta2[id2-1] == pos){
        ++sccNum; --id2; int v;
        do{
            v = sta1[--id1];
            scc[v] = sccNum;
        } while(sta1[id1] != pos);
    }
}

void solve(int n)
{
    memset(low, 0, sizeof(int) * (n + 1));
    memset(scc, 0, sizeof(int) * (n + 1));
    memset(in, 0, sizeof(bool) * (n + 1));
    memset(out, 0, sizeof(bool) * (n + 1));
    int i, j, ans1 = 0, ans2 = 0; id1 = id2 = sec = sccNum = 0;
    for(i = 1; i <= n; ++i)
        if(!low[i]) Garbow(i);
    for(i = 1; i <= n; ++i)
        for(j = head[i]; j != -1; j = E[j].next)
            if(scc[i] != scc[E[j].to]){
                out[scc[i]] = 1;
                in[scc[E[j].to]] = 1;
            }
    if(sccNum != 1){
        for(i = 1; i <= sccNum; ++i){
            if(!out[i]) ++ans2;
            if(!in[i]) ++ans1;
        }
        if(ans1 > ans2) ans2 = ans1;
    }else ans1 = 1;
    printf("%d\n%d\n", ans1, ans2);
}

int main()
{
    int n;
    while(scanf("%d", &n) == 1){
        getMap(n);
        solve(n);
    }
    return 0;
}
时间: 2024-10-28 05:34:25

POJ1236 Network of Schools 【强连通分量Garbow】的相关文章

POJ1236 Network of Schools (强连通分量,注意边界)

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 lis

[IOI1996] USACO Section 5.3 Network of Schools(强连通分量)

nocow上的题解很好. http://www.nocow.cn/index.php/USACO/schlnet 如何求强连通分量呢?对于此题,可以直接先用floyd,然后再判断. ---------------------------------------------------------------------------------- #include<cstdio> #include<iostream> #include<algorithm> #includ

Network of Schools(强连通分量+缩点) (问添加几个点最少点是所有点连接+添加最少边使图强连通)

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13801   Accepted: 5505 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

POJ - 1236 Network of Schools(强连通分量)

题目大意:有N个点,接着给出N个点所能连接的点. 问题1:如果要将一个信息传递给这N个点,至少需要传递给多少个点,然后让这些点进行传播,使N个点都得到信息 问题2:需要添加多少条边才能使这N个点能两两连通 解题思路:求出所有的强连通分量,接着缩点,再以桥为路径,建图 找出这张图中入度为0的,因为只有入度为0的才需要进行通知,其他的点可以通过其他边进行传达 需要添加多少个点,观察这张图,求出每个点的出度和入度,取max(入度为零的点的数量,出度为0的点数量) 注意当强连通分量只有1个的时候 #in

POJ 1236 Network of Schools(强连通分量)

题目地址:POJ 1236 这个题的大意是求最少往多少点发送消息可以使任意一个点都能收到消息和最少增加多少条边可以使图为连通图.对于第一个问题,可以求入度为0的强连通块的块数,因为只有入度为0的强连通块是无法从外界接受信息的,而只要有一个入度的话,那整个连通块就都可以接收到信息.第二个问题则是求入度为0的强连通块与出度为0的强连通块的个数的最大值. 代码如下: #include <iostream> #include <cstdio> #include <string>

POJ 1236 Network Of Schools (强连通分量模板题)

代码: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rev(i,a,b)

POJ 1236 Network of Schools (强连通分量缩点求度数)

题意: 求一个有向图中: (1)要选几个点才能把的点走遍 (2)要添加多少条边使得整个图强联通 分析: 对于问题1, 我们只要求出缩点后的图有多少个入度为0的scc就好, 因为有入度的scc可以从其他地方到达. 对于问题2, 每个入度为0的scc, 都可以补一条边可以变成强连通图, 每个出度为0的scc, 也可以补一条边使其变成强连通图. 所以答案就是max(入度为0scc个数,出度为0scc个数). #include<cstdio> #include<iostream> #inc

poj1236 Network of Schools ,求强连通分量(Tarjan算法),缩点

题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点 2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点 顶点数<= 100 求完强连通分量后,缩点,计算每个点的入度,出度. 第一问的答案就是入度为零的点的个数, 第二问就是max(n,m) // 入度为零的个数为n, 出度为零的个数为m. //kuangbin巨巨分析很棒! #include<cstdio> #include<cstring>

P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools

P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写一个程序计算,根据协议,为了让网络中所有的学校都用上新软件,必须接受新软件副本的最少学校数目(子任务 A).更进一步,我们想要确定通过给任意一个学校发送新软件,这个