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 }
  • 相关阅读:
    C#操作配置文件
    IIS的启动与停止命令
    我的SQL里哪个语句占用的CPU最多?
    Redis 安装
    redis启动出错Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
    多线程和异步
    mvc 使用Newtonsoft.Json进行序列化json数据
    深入理解JavaScript Hijacking原理
    C#中的partial class(部分类)
    在ASP.NET MVC中使用DropDownList
  • 原文地址:https://www.cnblogs.com/robin1998/p/6730936.html
Copyright © 2011-2022 走看看