N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。
问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
input format:
输入有多组样例,大约1000组。
每组样例第一行包含两个整数N,M(2<=N<=100),N代表学校的个数,M代表边的个数(M<N*N)
接下来M行,每行包含连个整数u,v,代表u可以向v单向发送数据。
output format
每组样例对应两行,分别是问题一和问题二的解。
sample input
7 8
1 2
2 3
3 1
1 4
4 5
5 6
6 4
7 6
sample output
2
2
----------------------------------------------------------------------------------
所需发放软件的数量为缩点后入度为0的点的个数,所需添加的边为入度为0和出度为0点的个数的较大者。
----------------------------------------------------------------------------------
# include <cstdio> # include <cstring> # define N 100 + 5 int n, m; int t, cols; int f[N], c[N], in[N], out[N]; char vis[N], g[N][N]; void read_graph(void) { int u, v; for (int i = 1; i <= n; ++i) { in[i] = 0; memset(g[i]+1, 0, sizeof(int)*n); } for (int i = 1; i <= m; ++i) { scanf("%d%d", &u, &v); g[u][v] = 1; } } void dfs(int u) { vis[u] = 1; for (int v = 1; v <= n; ++v) if (!vis[v] && g[u][v]) dfs(v); f[++t] = u; } void rdfs(int u) { vis[u] = 1; c[u] = cols; for (int v = 1; v <= n; ++v) if (!vis[v] && g[v][u]) rdfs(v); } void solve(void) { t = 0; memset(vis+1, 0, sizeof(char)*n); for (int i = 1; i <= n; ++i) if (!vis[i]) dfs(i); cols = 0; memset(vis+1, 0, sizeof(char)*n); for (int i = n; i >= 1; --i) if (!vis[f[i]]) ++cols, rdfs(f[i]); if (cols == 1) {printf("1\n0\n"); return ;} memset(in+1, 0, sizeof(int)*cols); memset(out+1, 0, sizeof(int)*cols); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) { if(g[i][j] && c[i] != c[j]) { ++in[c[j]]; ++out[c[i]]; } } int zin = 0, zout = 0; for (int i = 1; i <= cols; ++i) { if (in[i] == 0) ++zin; if (out[i] == 0) ++zout; } printf("%d\n%d\n", zin, zin>zout ? zin:zout); } int main() { while (~scanf("%d%d", &n, &m)) { read_graph(); solve(); } return 0; }