POJ1236(强连通分量)

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

IOI 1996

题意:问题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\n%d\n", 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 }
时间: 2024-08-24 19:12:58

POJ1236(强连通分量)的相关文章

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

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

【连通图|强连通分量+缩点】POJ-1236 Network of Schools

Network of Schools Time Limit: 1000MS Memory Limit: 10000K 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 softwa

POJ1236 (Network of Schools,Tarjan,强连通分量)

转载自:http://www.tuicool.com/articles/EnMFFja 原创:kuangbin 题意:  一个有向图,求: 1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点 2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点,即成为一个强连通分量 思路: 求完强连通分量后,缩点,计算每个点的入度,出度. 第一问的答案就是入度为零的点的个数, 第二问就是max(n,m)  入度为零的个数为n, 出度为零的个数为m 思路详解: 1. 求出所有强连通分

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

题目链接: http://poj.org/problem?id=1236 题目大意: N台电脑之间能够通过有向边(u,v)从第u台电脑传输文件到第v台电脑.如果给第u台电脑投放 一个文件,那么这个文件就能通过有向边传输到第v台电脑上,给你N台电脑的连接情况. 那么问题来了:1.最少向这N台电脑中的几台电脑投放文件,就能使N台电脑都能接收到文件. 2.最少向这N台电脑构成的图中添加几条边,使只向一台电脑投放文件,就能够是N台电脑都 能接收到文件. 思路: 该图中的文件具有传递性.很快发现强连通的特

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

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

[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)

题目链接:http://poj.org/problem?id=1236 这题本来是个强连通分量板子题的,然而弱很久不写tarjan所以生疏了一下,又看这数据范围觉得缩点这个事情可以用点到点之间的距离来判断不知道群巨兹磁不兹磁……下面弱就给大家搞一发如何用floyd和并查集来缩点……大致的思路就是先floyd跑出所有距离,然后O(n^2)找两两都可达的点,把它们的关系用并查集来维护.接下来O(n)找并查集里的代表元素.这个时候应当特判一下连通块为1的时候.再O(n^2)找出所有单向边,然后更新所有

poj1236 Network of Schools【强连通分量(tarjan)缩点】

转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4316263.html  ---by 墨染之樱花 [题目链接]http://poj.org/problem?id=1236 [题目描述]给一张有向图,表示学校通信网络,边<u,v>代表信息可以由u传递到v.现要完成两个任务:1.求最少把几个点作为信息传递的起点就能让信息转达到所有节点 2.最少在添加几条边就能使任意两点间可达(构造强连通分量) [思路]先利用tarjan缩点使整个图化为DAG

有向图的强连通分量(tarjan算法)

强连通分量 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(strongly connected components). 考虑强连通分量C,设其中第一个被发现的点为x,则,C中其他的点都是x的后代.我们希望在x访问完成时立即输出C(可以同时记录C,输出代表

POJ2375 Cow Ski Area【Tarjan】【强连通分量】

题目链接: http://poj.org/problem?id=2375 题目大意: 有一片供奶牛滑雪的滑雪场,可供滑雪的区域是W(宽)*L(长)的矩阵.上边有W*L个点.规定 奶牛从一个点只能向它上.下.左.右相邻的并且高度不大于它的点运动.现在想要在某些 点对之间架设缆车,使得奶牛可以从较低的地方想较高的地方运动,那么问题来了:最少需 要多少辆这样的缆车就可以使奶牛从每个点运动到可供滑雪区域的每个角落. 思路: 把奶牛符合从点u移动到点v的条件当做一条单向边.那么所有点和边就可以构成有向图.