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 }
  • 相关阅读:
    清除浮动的方式
    网页在线测试工具
    仿京东左侧菜单 hover效果-简易demo
    原生js,插入元素
    知识补漏
    css3动画
    java微信开发(wechat4j)——支持微信JS-SDK的jsapi_ticket中控服务器
    java微信开发(wechat4j)——access_token中控服务器实现
    java微信开发(wechat4j)——wechat4j配置文件解读
    java微信开发(wechat4j)——设置响应微信参数
  • 原文地址:https://www.cnblogs.com/robin1998/p/6730936.html
Copyright © 2011-2022 走看看