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

转载自:http://www.tuicool.com/articles/EnMFFja

原创:kuangbin

题意:

   一个有向图,求:

  1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点

  2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点,即成为一个强连通分量

思路:

  求完强连通分量后,缩点,计算每个点的入度,出度。

  第一问的答案就是入度为零的点的个数,

  第二问就是max(n,m)  入度为零的个数为n, 出度为零的个数为m

思路详解:

     1. 求出所有强连通分量
     2. 每个强连通分量缩成一点,则形成一个有向无环图DAG。
     3. DAG上面有多少个入度为0的顶点,问题1的答案就是多少
在DAG上要加几条边,才能使得DAG变成强连通的,问题2的答案就是多少
加边的方法:
要为每个入度为0的点添加入边,为每个出度为0的点添加出边
假定有 n 个入度为0的点,m个出度为0的点,如何加边?
把所有入度为0的点编号 0,1,2,3,4 ....N -1
每次为一个编号为i的入度0点可达的出度0点,添加一条出边,连到编号为(i+1)%N 的那个出度0点,
这需要加n条边
若 m <= n,则
加了这n条边后,已经没有入度0点,则问题解决,一共加了n条边
若 m > n,则还有m-n个入度0点,则从这些点以外任取一点,和这些点都连上边,即可,这还需加m-n条边。
所以,max(m,n)就是第二个问题的解
此外:当只有一个强连通分支的时候,就是缩点后只有一个点,虽然入度出度为0的都有一个,但是实际上不需要增加清单的项了,所以答案是1,0;

Tarjan算法浅解:

                     

  1.过程:

    (1)dfn[i]表示dfs时达到顶点i的时间戳

        low[i]表示i所能直接或间接达到    时间最小的顶点(比如上图  3->1   low[3] = 1)

    (2)time初始化为0,在dfs遍历到u时,low[u]=dfn[u]=time++,u入栈

             扫描u的邻接顶点v,如果 v没有被访问则dfs(v);

              low[u]=min(low[u],low[v])

                如果邻接顶点在此次已经被扫描:即dfn[v] != 0 和 belong[v] == 0 , low[u] = min(low[u],dfn[v]);

      如果low[v]=dfn[v]时,栈里v以及v以上的顶点全部出栈,且刚刚出栈的就是一个极大强连通分量。

  2.大概原理:

    填坑......

代码:

 1 //#include<bits/stdc++.h>
 2 #include<vector>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<stack>
 7 using namespace std;
 8 typedef long long ll;
 9
10 const int maxn = 100 + 10;
11
12 vector<int> G[maxn];
13 int n,dfn[maxn],low[maxn],belong[maxn],dfs_clock,scc_cnt;
14 stack<int> S;
15
16 /**
17
18     Tarjan算法
19
20 */
21
22 void dfs(int u){
23     dfn[u] = low[u] = ++dfs_clock;
24     S.push(u);
25     for(int i = 0 ; i < G[u].size() ; i ++){
26         int v = G[u][i];
27         if(!dfn[v]){
28             dfs(v);
29             low[u] = min(low[u],low[v]);
30         }else if(!belong[v]){
31             low[u] = min(low[u],dfn[v]);
32         }
33     }
34     if(low[u] == dfn[u]){
35         scc_cnt++;
36         for(;;){
37             int x = S.top(); S.pop();
38             belong[x] = scc_cnt;
39             if(x == u) break;
40         }
41     }
42 }
43
44 void scc(int n){
45     dfs_clock = scc_cnt = 0;
46     memset(dfn,0,sizeof(dfn));
47     memset(belong , 0 ,sizeof(belong));
48     for(int i = 0 ; i < n ; i ++)
49         if(!dfn[i]) dfs(i);
50
51 }
52
53 int main(){
54     int x;
55     while(scanf("%d",&n) != EOF && n){
56         for(int i = 0 ; i <= n ; i ++)  G[i].clear();
57         for(int i = 0 ; i < n ; i ++){
58             while(scanf("%d",&x),x){
59                 --x;
60                 G[i].push_back(x);
61             }
62         }
63         scc(n);
64         if(scc_cnt == 1){
65             printf("1\n0\n");
66             continue;
67         }
68         int in[maxn],out[maxn],in_tot = 0 , out_tot = 0;
69         memset(in,0,sizeof(in));
70         memset(out,0,sizeof(out));
71         for(int i = 0 ; i < n ; i ++){
72             for(int j = 0 ; j < G[i].size() ; j ++){
73                 int v = G[i][j];
74 /**
75     遍历每个点.
76         遍历与该点相连的点
77             判断两个点是否同一个连通分量
78             如果不是,则改变缩点后的出入度
79
80 */
81                 if(belong[i] != belong[v]){
82                     out[ belong[i] ] ++;
83                     in [ belong[v] ] ++;
84                 }
85             }
86         }
87         for(int i = 1 ; i <= scc_cnt ; i ++){
88             if(!in[i]) in_tot++;
89             if(!out[i]) out_tot++;
90         }
91
92         printf("%d\n%d\n",in_tot,max(in_tot,out_tot));
93     }
94     return 0;
95 }
时间: 2024-10-07 00:37:18

POJ1236 (Network of Schools,Tarjan,强连通分量)的相关文章

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

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

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11180   Accepted: 4448 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

POJ 1236 Network of Schools(强连通分量)

POJ 1236 Network of Schools 链接:http://poj.org/problem?id=1236 题意:有一些学校连接到一个计算机网络.这些学校之间达成了一个协议:每个学校维护着一个学校列表,它向学校列表中的学校发布软件.注意,如果学校B 在学校A 的列表中,则A 不一定在B 的列表中. 任务A:计算为使得每个学校都能通过网络收到软件,你至少需要准备多少份软件拷贝. 任务B:考虑一个更长远的任务,想确保给任意一个学校发放一个新的软件拷贝,该软件拷贝能发布到网络中的每个学

POJ 1236 Network of Schools 有向图强连通分量

参考这篇博客: http://blog.csdn.net/ascii991/article/details/7466278 #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <vector> #include <stack> using namespace std; typedef long long LL; c

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

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

POJ 1236 Network of Schools(强连通 Tarjan+缩点)

POJ 1236 Network of Schools(强连通 Tarjan+缩点) ACM 题目地址:POJ 1236 题意: 给定一张有向图,问最少选择几个点能遍历全图,以及最少加入?几条边使得有向图成为一个强连通图. 分析: 跟HDU 2767 Proving Equivalences(题解)一样的题目,只是多了个问题,事实上转化成DAG后就不难考虑了,事实上仅仅要选择入度为0的点即可了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools

P2746 [USACO5.3]校园网Network of Schools// POJ1236: Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写一个程序计算,根据协议,为了让网络中所有的学校都用上新软件,必须接受新软件副本的最少学校数目(子任务 A).更进一步,我们想要确定通过给任意一个学校发送新软件,这个

hdu1269 Tarjan强连通分量 模板(转)

#include<stdio.h> #include<iostream> #include<vector> using namespace std; const int maxn=10010; vector<int>g[maxn]; int Bcnt; int Top; int Index; int low[maxn],dfn[maxn]; int belong[maxn],stack[maxn]; int instack[maxn]; void Init_

tarjan 强连通分量

一.强连通分量定义 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(stronglyconnected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(stronglyconnectedcomponents)SCC. 以上是摘自百科的一段对有向图强连通图分量的形式化定义.其实不难理解,举个例子 如上图,{a,b,c,d}为一个强连通分量,{e}