zoukankan      html  css  js  c++  java
  • POJ-1236 Network of Schools 【强连通分量+缩点】

    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
    
    

    题解:

    题目比较简单,先算出强连通分量,再缩点,算出缩点后图的每个点的入度和出度,可以发现,只要给每个入度为0的点分配软件,就是最优策略(因为入度大于0的点一定可以从前一个点获得),B任务的解就是max(入度为0的点数,出度为0的点数),易知要使图强连通,尾接到头是最优方案,谁大谁就是最终解。(注意:如果强连通分量只有一个的时候一定要令ans2=0,因为那时即使所有点的入度出度虽然不为0但根据该算法是不计算,亲测不特判会WA)

    代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<vector>
     6 #include<set>
     7 #include<queue>
     8 #include<stack>
     9 using namespace std;
    10 #define M(a, b) memset(a, b, sizeof(a))
    11 #define INF 0x3f3f3f3f
    12 const int N = 100 + 5;
    13 int pre[N], sccno[N], dfs_clock, scc_cnt;
    14 int ind[N], od[N];
    15 vector<int> G[N];
    16 stack<int> S;
    17 
    18 int dfs(int u) {
    19     int lowu = pre[u] = ++dfs_clock;
    20     S.push(u);
    21     for (int i = 0; i < G[u].size(); ++i) {
    22         int v = G[u][i];
    23         if (!pre[v]) {
    24             int lowv = dfs(v);
    25             lowu = min(lowu, lowv);
    26         }
    27         else if (!sccno[v]) {
    28             lowu = min(lowu, pre[v]);
    29         }
    30     }
    31     if (lowu == pre[u]) {
    32         ++scc_cnt;
    33         while (true) {
    34             int x = S.top(); S.pop();
    35             sccno[x] = scc_cnt;
    36             if (x == u) break;
    37         }
    38     }
    39     return lowu;
    40 }
    41 
    42 void find_scc(int n) {
    43     M(pre, 0); M(sccno, 0);
    44     dfs_clock = scc_cnt = 0;
    45     for (int i = 0; i < n; ++i) 
    46         if (!pre[i]) dfs(i); 
    47 }
    48 
    49 int main() {
    50     int n, v;
    51     while (~scanf("%d", &n)) {
    52         for (int u = 0; u < n; ++u) {
    53             while(true) {
    54                 scanf("%d", &v); --v;
    55                 if (v == -1) break;
    56                 G[u].push_back(v);
    57             }
    58         }
    59         find_scc(n);
    60         M(ind, 0); M(od, 0);
    61         for (int u = 0; u < n; ++u)
    62             for (int i = 0; i < G[u].size(); ++i) {
    63                 int v = G[u][i];
    64                 if (sccno[u] != sccno[v]) {
    65                     od[sccno[u]]++, ind[sccno[v]]++;
    66                 }
    67             }
    68         int in0 = 0, out0 = 0;
    69         for (int i = 1; i <= scc_cnt; ++i) {
    70             if (!ind[i]) in0++;
    71             if (!od[i]) out0++;
    72         }
    73         int ans2 = max(in0, out0);
    74         if (scc_cnt == 1) ans2 = 0;
    75         printf("%d
    %d
    ", in0, ans2);
    76     }
    77 
    78     return 0;
    79 }
  • 相关阅读:
    Oracle插入特殊字符问题
    Oracle数据库中IN参数个数超过1000的问题
    解决tomcat 内存溢出问题
    IDEA 最新版本 破解教程(windows,mac皆可用)(新版本已失效)
    javascript将字符串中的多个空格替换为一个空格的正则实例
    删除一个表中重复的数据
    mac/linux 解决启动命令行出现declare问题
    iftop 安装以及相关参数及说明(转载自csdn)
    centos安装与卸载postgresql
    jquery实现自动补全邮箱地址
  • 原文地址:https://www.cnblogs.com/robin1998/p/6730936.html
Copyright © 2011-2022 走看看