http://poj.org/problem?id=1236
N个学校间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。
(1):初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
(2):至少需要添加几条传输线路,使得任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
即:
给定一个有向图,求:
(1)至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点。
(2)至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点。
即:
(1)强连通分量缩点中【入度为0的个数】。
(2)强连通分量缩点中【入度为0的个数】和【出度为0的分量个数】的较大值。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
const int maxn=105;
int n;
vector <int> G[maxn];
vector <int> rG[maxn];
vector <int> vs;
bool vis[maxn];
int cmp[maxn];
int in[maxn],out[maxn];
void add(int from,int to){
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v){
vis[v]=true;
for (int i=0;i<G[v].size();i++){
if (!vis[G[v][i]]){
dfs(G[v][i]);
}
}
vs.push_back(v);
}
void rdfs(int v,int k){
vis[v]=true;
cmp[v]=k;
for (int i=0;i<rG[v].size();i++){
if (!vis[rG[v][i]]){
rdfs(rG[v][i],k);
}
}
}
int scc(){
memset(vis,0,sizeof(vis));
vs.clear();
for (int i=1;i<=n;i++){
if (!vis[i]){
dfs(i);
}
}
memset(vis,0,sizeof(vis));
int k=0;
for (int i=vs.size()-1;i>=0;i--){
if (!vis[vs[i]]){
rdfs(vs[i],k++);
}
}
return k;
}
int main(){
cin >> n;
for (int i=1;i<=n;i++){
int v;
while (cin >> v && v){
add(i,v);
}
}
int Scc=scc();
if (Scc==1){
cout << "1" << endl << "0" << endl;
}
else{
for (int u=1;u<=n;u++){
for (int i=0;i<G[u].size();i++){
int v=G[u][i];
if (cmp[u]!=cmp[v]){
out[cmp[u]]++;
in[cmp[v]]++;
}
}
}
int zero_in=0,zero_out=0;
for (int i=0;i<Scc;i++){
if (in[i]==0) zero_in++;
if (out[i]==0) zero_out++;
}
cout << zero_in << endl;
cout << max(zero_in,zero_out) << endl;
}
}