zoukankan      html  css  js  c++  java
  • POJ1236(KB9-A 强连通分量)

    Network of Schools

    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 19326   Accepted: 7598

    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
    

    Source

     
    题意:问题1:对于有向图,问选多少个点出发,可以走遍所有点。
       问题2:对于有向图,问最少加几条边,使得图强连通
     
    思路:问题1:强连通分量缩点后得到DAG,入度为0的连通分量的数量即为答案。
       问题2:强连通分量缩点后得到DAG,出度为0的连通分量连向入度为0的连通分量,答案为max(出度为0的连通分量数,入度为0的连通分量数)
            但是当只有一个强连通分量的时候,答案为0。
     
      1 //2017-08-20
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <cmath>
      7 #include <vector>
      8 
      9 using namespace std;
     10 
     11 const int N = 110;
     12 int n, in_degree[N], out_degree[N];
     13 bool vis[N];
     14 vector<int> G[N];
     15 vector<int> rG[N];
     16 vector<int> vs;
     17 int cmp[N];
     18 
     19 void add_edge(int u, int v){
     20     G[u].push_back(v);
     21     rG[v].push_back(u);
     22 }
     23 
     24 //input: u 顶点
     25 //output: vs 后序遍历顺序的顶点列表
     26 void dfs(int u){
     27     vis[u] = true;
     28     for(int i = 0; i < G[u].size(); i++){
     29         int v = G[u][i];
     30         if(!vis[v])
     31           dfs(v);
     32     }
     33     vs.push_back(u);
     34 
     35 }
     36 
     37 //input: u 顶点编号; k 拓扑序号
     38 //output: cmp[] 强连通分量拓扑序
     39 void rdfs(int u, int k){
     40     vis[u] = true;
     41     cmp[u] = k;
     42     for(int i = 0; i < rG[u].size(); i++){
     43         int v = rG[u][i];
     44         if(!vis[v])
     45           rdfs(v, k);
     46 
     47     }
     48 
     49 }
     50 
     51 //Strongly Connected Component 强连通分量
     52 //input: n 顶点个数
     53 //output: k 强连通分量数;
     54 int scc(){
     55     memset(vis, 0, sizeof(vis));
     56     vs.clear();
     57     for(int u = 1; u <= n; u++)
     58       if(!vis[u]){
     59           dfs(u);
     60       }
     61     int k = 0;
     62     memset(vis, 0, sizeof(vis));
     63     for(int i = vs.size()-1; i >= 0; i--)
     64       if(!vis[vs[i]])
     65         rdfs(vs[i], k++);
     66     return k;
     67 }
     68 
     69 void solve(){
     70     int k = scc();
     71     int ans = 0;
     72     memset(in_degree, 0, sizeof(in_degree));
     73     memset(out_degree, 0, sizeof(out_degree));
     74     for(int u = 1; u <= n; u++){
     75         memset(vis, 0, sizeof(vis));
     76         for(int i = 0; i < G[u].size(); i++){
     77             int v = G[u][i];
     78             if(vis[v])continue;
     79             vis[v] = 1;
     80             if(cmp[u] != cmp[v]){
     81                 out_degree[cmp[u]]++;
     82                 in_degree[cmp[v]]++;
     83             }
     84         }
     85     }
     86     int a = 0, b = 0;
     87     for(int i = 0; i < k; i++){
     88           if(in_degree[i] == 0)a++;
     89         if(out_degree[i] == 0)b++;
     90     }
     91     ans = max(a, b);
     92     if(k == 1)ans = 0;
     93     printf("%d
    %d
    ", a, ans);
     94 }
     95 
     96 int main()
     97 {
     98     while(scanf("%d", &n)!=EOF){
     99         for(int u = 1; u <= n; u++){
    100             G[u].clear();
    101             rG[u].clear();
    102         }
    103         int v;
    104         for(int u =1; u <= n; u++){
    105             while(scanf("%d", &v)==1 && v){
    106                 add_edge(u, v);
    107             }
    108         }
    109         solve();
    110     }
    111 
    112     return 0;
    113 }
  • 相关阅读:
    asyncio异步IO--协程(Coroutine)与任务(Task)详解
    python爬虫实战:利用scrapy,短短50行代码下载整站短视频
    深入理解Git的实现原理
    Upsource 代码审查工具安装及使用
    MAC MAMP集成环境安装 PHP 扩展
    千万数据量数据表分表实践
    设计模式:序言
    设计模式 行为型
    PHP5底层原理之变量
    PHP5底层原理之垃圾回收机制
  • 原文地址:https://www.cnblogs.com/Penn000/p/7400488.html
Copyright © 2011-2022 走看看