校园网络
时间限制:3000 ms | 内存限制:65535 KB
难度:5
南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件。但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件。
现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件可用。
每组测试数据的第一行是一个整数M,表示共有M个系(2<=M<=100)。
随后的M行,每行都有一些整数,其中的第i行表示系i允许这几个系复制并使用系i的软件。每行结尾都是一个0,表示本行输入结束。如果某个系不允许其它任何系使用该系软件,则本行只有一个0.
1 5 2 4 3 0 4 5 0 0 0 1 0
2
思路:
强连通分量缩点后,再找入度为0的节点数 和 出度为0的节点数 的最大值即可。
AC:
#include <cstdio> #include <cstring> #include <algorithm> #include <stack> #include <vector> using namespace std; const int VMAX = 105; int in[VMAX], out[VMAX]; vector<int> G[VMAX]; int n; int dfs_clock, scc_cnt; int pre[VMAX], cmp[VMAX], low[VMAX]; stack<int> s; void dfs (int u) { low[u] = pre[u] = ++dfs_clock; s.push(u); for (int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if (!pre[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if (!cmp[v]) { low[u] = min(low[u], pre[v]); } } if (pre[u] == low[u]) { ++scc_cnt; for ( ;;) { int x = s.top(); s.pop(); cmp[x] = scc_cnt; if (x == u) break; } } } void scc() { scc_cnt = dfs_clock = 0; memset(cmp, 0, sizeof(cmp)); memset(pre, 0, sizeof(pre)); for (int i = 1; i <= n; ++i) { if (!pre[i]) dfs(i); } } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) { G[i].clear(); in[i] = out[i] = 0; } for (int i = 1; i <= n; ++i) { int num; while (~scanf("%d", &num) && num) { G[i].push_back(num); } } scc(); for (int i = 1; i <= n; ++i) { for (int j = 0; j < G[i].size(); ++j) { int v = G[i][j]; ++in[ cmp[v] ]; ++out[ cmp[i] ]; } } int in_num = 0, out_num = 0; for (int i = 1; i <= scc_cnt; ++i) { if (!in[i]) ++in_num; if (!out[i]) ++out_num; } printf("%d\n", max(in_num, out_num)); } return 0; }
相关推荐
Prim算法则是从一个顶点出发,逐步添加边,始终保证增加的边连接的是两个不同的连通分量,直到所有顶点都在同一连通分量中。 在实际的【校园导游系统】中,开发者可能会结合这些算法,根据校园地图构建图模型,实现...
理解这些类型对于分析有向图的性质,如强连通分量、拓扑排序等至关重要。 5. **无环有向图(DAG)**:问题1006提到了DAG,即无环有向图。DAG中的节点没有环路,拓扑排序是DAG的一个常见应用,它返回一个节点的线性...
这是一种常见的解决图论问题的方法,尤其适用于寻找连通分量。在实际面试或笔试中,这种问题有助于评估应聘者对于图论、递归以及复杂度分析的理解。 总之,这个题目旨在测试应聘者的编程技能,尤其是对图的遍历和...
并查集的核心思想是通过一个数组`friends`来表示每个节点(在这里是人)的父节点,数组`rank`记录每个连通分量的大小(树的高度)。`init`函数用于初始化每个节点为自己的父节点,`findRoot`函数用于查找给定节点的...
7. 图论算法:Dijkstra最短路径算法、Floyd-Warshall所有对最短路径算法、拓扑排序、强连通分量等。 8. 字符串处理:KMP算法、Manacher's Algorithm、Rabin-Karp模式匹配算法等。 9. 排序和搜索算法的时间复杂度与...
图的算法包括最短路径(Dijkstra算法、Floyd-Warshall算法)、拓扑排序、强连通分量等。 散列表(哈希表)是通过散列函数实现快速查找的数据结构,它可以实现近乎常数时间的查找、插入和删除。然而,冲突(两个元素...
- **克鲁斯卡尔(Kruskal)算法**:按边的权重从小到大排序,然后尝试添加每一条边,如果添加这条边不会形成环路(即边的两个端点不在同一个连通分量中),则将其加入最小生成树。这种方法适合稀疏图,因为边的添加...
- 方法: 可以使用图论中的连通分量来解决此问题,通过构建学生之间的邻接矩阵或邻接表,然后利用深度优先搜索(DFS)或广度优先搜索(BFS)算法找出所有连通分量。 - 知识点: 图论、连通分量、DFS/BFS算法。 以上是...