`
Simone_chou
  • 浏览: 197133 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

校园网络(强连通分量)

    博客分类:
  • NYOJ
 
阅读更多

校园网络

时间限制:3000 ms  |  内存限制:65535 KB
难度:5
 
描述

南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件。但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件。

现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件可用。

 
输入
第一行输入一个整数T,表示测试数据的组数(T<10)
每组测试数据的第一行是一个整数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;
}

 

 

分享到:
评论

相关推荐

    校园导游系统(c语言开发).7z

    Prim算法则是从一个顶点出发,逐步添加边,始终保证增加的边连接的是两个不同的连通分量,直到所有顶点都在同一连通分量中。 在实际的【校园导游系统】中,开发者可能会结合这些算法,根据校园地图构建图模型,实现...

    图算法例题1

    理解这些类型对于分析有向图的性质,如强连通分量、拓扑排序等至关重要。 5. **无环有向图(DAG)**:问题1006提到了DAG,即无环有向图。DAG中的节点没有环路,拓扑排序是DAG的一个常见应用,它返回一个节点的线性...

    今日头条2019校园招聘笔试2.doc

    这是一种常见的解决图论问题的方法,尤其适用于寻找连通分量。在实际面试或笔试中,这种问题有助于评估应聘者对于图论、递归以及复杂度分析的理解。 总之,这个题目旨在测试应聘者的编程技能,尤其是对图的遍历和...

    今日头条2019校园招聘笔试1.doc

    并查集的核心思想是通过一个数组`friends`来表示每个节点(在这里是人)的父节点,数组`rank`记录每个连通分量的大小(树的高度)。`init`函数用于初始化每个节点为自己的父节点,`findRoot`函数用于查找给定节点的...

    2018名企校招笔试真题精选技术篇.pdf.zip

    7. 图论算法:Dijkstra最短路径算法、Floyd-Warshall所有对最短路径算法、拓扑排序、强连通分量等。 8. 字符串处理:KMP算法、Manacher's Algorithm、Rabin-Karp模式匹配算法等。 9. 排序和搜索算法的时间复杂度与...

    数据结构试题库答案

    图的算法包括最短路径(Dijkstra算法、Floyd-Warshall算法)、拓扑排序、强连通分量等。 散列表(哈希表)是通过散列函数实现快速查找的数据结构,它可以实现近乎常数时间的查找、插入和删除。然而,冲突(两个元素...

    广州大学 数据结构实验报告 实验三 图的操作与实现

    - **克鲁斯卡尔(Kruskal)算法**:按边的权重从小到大排序,然后尝试添加每一条边,如果添加这条边不会形成环路(即边的两个端点不在同一个连通分量中),则将其加入最小生成树。这种方法适合稀疏图,因为边的添加...

    数据结构课程设计

    - 方法: 可以使用图论中的连通分量来解决此问题,通过构建学生之间的邻接矩阵或邻接表,然后利用深度优先搜索(DFS)或广度优先搜索(BFS)算法找出所有连通分量。 - 知识点: 图论、连通分量、DFS/BFS算法。 以上是...

Global site tag (gtag.js) - Google Analytics