CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址

CCF CSP 201709-4 通信网络

问题描述

  某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只能单向传递信息,即一条从部门a到部门b的通路只能由ab传递信息。信息可以通过中转的方式进行传递,即如果a能将信息传递到bb又能将信息传递到c,则a能将信息传递到c。一条信息可能通过多次中转最终到达目的地。
  由于保密工作做得很好,并不是所有部门之间都互相知道彼此的存在。只有当两个部门之间可以直接或间接传递信息时,他们才彼此知道对方的存在。部门之间不会把自己知道哪些部门告诉其他部门。

  上图中给了一个4个部门的例子,图中的单向边表示通路。部门1可以将消息发送给所有部门,部门4可以接收所有部门的消息,所以部门1和部门4知道所有其他部门的存在。部门2和部门3之间没有任何方式可以发送消息,所以部门2和部门3互相不知道彼此的存在。
  现在请问,有多少个部门知道所有N个部门的存在。或者说,有多少个部门所知道的部门数量(包括自己)正好是N

输入格式

  输入的第一行包含两个整数NM,分别表示部门的数量和单向通路的数量。所有部门从1到N标号。
  接下来M行,每行两个整数ab,表示部门a到部门b有一条单向通路。

输出格式

  输出一行,包含一个整数,表示答案。

样例输入

4 4
1 2
1 3
2 4
3 4

样例输出

2

样例说明

  部门1和部门4知道所有其他部门的存在。

评测用例规模与约定

  对于30%的评测用例,1 ≤ N ≤ 10,1 ≤ M ≤ 20;
  对于60%的评测用例,1 ≤ N ≤ 100,1 ≤ M ≤ 1000;
  对于100%的评测用例,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000。

解析

如果图无环,计算每一个顶点父节点的个数及子节点的个数,如果二者之和加一等于总节点的个数,那么就是所求解的知道N个节点存在的节点。

统计一个节点父节点的个数可以通过N个深度优先搜索得到。从每一个节点开始进行深度优先搜索,每到达一个节点,该节点的计数加一。复杂度为O(V(V+E))

将图的所有边反向,便可以统计一个节点子节点的个数。

如果图存在环,在同一个强连通分量内的节点互相为父子节点,上面的方法便失效了。解决方案是首先进行强连通分量的分解。代码中使用了Kosaraju算法进行强连通分量的分解。复杂度为O(V+E)

分解后得到每一个顶点的强连通分量标号。

然后计算每一个节点父强连通分量的个数与子强连通分量的个数。这一步从每一个强连通分量中选择一个顶点开始进行深度优先搜索,如果当前所在强连通分量的标签与起始节点强连通分量标签不同,则该节点计数加一。

如果一个顶点父强连通分量的个数加上子强连通分量的个数加一等于总强连通分量个数,那么这个节点知道所有节点的存在。

代码

C++

#include <iostream>
#include <vector>
#include <algorithm>
#define MAX_V 1001
using namespace std; int N, M;
vector<int> G[MAX_V], rG[MAX_V];
vector<int> postorder;
bool used[MAX_V];
int label[MAX_V]; // 每一个节点所属强连通分量的标号
int sccv[MAX_V]; // 每一个强连通分量的一个顶点
int nparent[MAX_V], nchild[MAX_V]; // 每一个节点父/子强连通分量个数 // 生成图的后序遍历
void dfs(int u) {
for(int i=; i<G[u].size(); i++) {
int v = G[u][i];
if(!used[v]) {
used[v] = true;
dfs(v);
}
}
postorder.push_back(u);
} int rdfs(int u, int l) {
label[u] = l;
for(int i=; i<rG[u].size(); i++) {
int v = rG[u][i];
if(!used[v]) {
used[v] = true;
rdfs(v, l);
}
}
} // Kosaraju算法 分解强连通分量
int SCC() {
fill(used, used+MAX_V, );
for(int n=; n<=N; n++) {
if(!used[n]) {
used[n] = true;
dfs(n);
}
}
fill(used, used+MAX_V, );
int l = ;
for(int n=N-; n>=; n--) {
int v = postorder[n];
if(!used[v]) {
l++;
used[v] = true;
rdfs(v, l);
sccv[l] = v;
}
}
return l;
} // 统计u所在强连通分量能够到达的其它强连通分量
void dfs2(int u, int l, int (&nparent)[MAX_V], vector<int> (&G)[MAX_V]) {
if(label[u] != l) nparent[u]++;
for(int i=; i<G[u].size(); i++) {
int v = G[u][i];
if(!used[v]) {
used[v] = true;
dfs2(v, l, nparent, G);
}
}
} int main() {
cin >> N >> M;
for(int m=; m<M; m++) {
int a, b;
cin >> a >> b;
G[a].push_back(b);
rG[b].push_back(a);
} int numc = SCC(); // 统计每一个顶点父强连通分量个数
for(int i=; i<=numc; i++) {
fill(used, used+MAX_V, );
int v = sccv[i];
used[v] = true;
dfs2(v, label[v], nparent, G);
} // 统计每一个顶点子强连通分量个数
for(int i=; i<=numc; i++) {
fill(used, used+MAX_V, );
int v = sccv[i];
used[v] = true;
dfs2(v, label[v], nchild, rG);
} int cnt = ;
for(int n=; n<=N; n++) {
// 如果父强连通分量个数加子强连通分量个数加一等于总强连通分量个数
if(nparent[n]+nchild[n]+==numc) cnt++;
}
cout << cnt;
}

CCF CSP 201709-4 通信网络的更多相关文章

  1. CCF CSP 201403-4 无线网络

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-4 无线网络 问题描述 目前在一个很大的平面房间里有 n 个无线路由器,每个无线路 ...

  2. CCF CSP 201503-4 网络延时

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201503-4 网络延时 问题描述 给定一个公司的网络,由n台交换机和m台终端电脑组成,交换机 ...

  3. ccf认证 201709-4 通信网络 java实现

    试题编号:                                                               201709-4 试题名称: 通信网络 时间限制: 1.0s 内 ...

  4. csp 通信网络

    http://blog.csdn.net/zyy_1998/article/details/78334496 试题编号: 201709-4 试题名称: 通信网络 时间限制: 1.0s 内存限制: 25 ...

  5. 通信网络 ccf

    试题编号: 201709-4 试题名称: 通信网络 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只 ...

  6. CCF(通信网络):简单DFS+floyd算法

    通信网络 201709-4 一看到题目分析了题意之后,我就想到用floyd算法来求解每一对顶点的最短路.如果一个点和任意一个点都有最短路(不为INF),那么这就是符合的一个答案.可是因为题目超时,只能 ...

  7. 小dai浅谈通信网络(一)——引子

    说起通信网络,首先来看一个场景: 场景模式: 小明和小刚在闹市碰面. 小明对小刚大声喊道:"小刚,你好啊!" 小刚摇手答到:"你好,小明!" 就这么几句简单的话 ...

  8. 浅谈通信网络(三)——TCP/IP协议

    简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...

  9. CCF CSP 认证

    参加第八次CCF CSP认证记录 代码还不知道对不对,过两天出成绩. 成绩出来了,310分. 100+100+100+10+0: 考试13:27开始,17:30结束,提交第4题后不再答题,只是检查前四 ...

随机推荐

  1. Ansible8:Playbook循环

    目录 1.with_items 2.with_nested嵌套循环 3.with_dict 4.with_fileglob文件匹配遍历 5.with_lines 6.with_subelement遍历 ...

  2. day10 浅谈面向对象编程

    面向对象编程:第一步找名词,名词是问题域中的. 第二步概括名词设计成类.某些名词可以浓缩包含到其它名词中,成为其属性. 第三步找动词,动词也是问题域中的.   第四步概括动词设计成方法.动作的产生往往 ...

  3. Shader 学习工具篇 可视化公式工具ZGrapher

    大家好,我是怒风,本篇介绍公式可视化公式工具ZGrapher,尝试通过可视化的方式分析一下Shader中应用的公式,以求帮助初学者快速理解Shader编程中的一些常用公式 本篇的目的两个, 第一,介绍 ...

  4. HDU 1717 小数化分数2 数学题

    解题报告:输入一个小于1的小数,让你把这个数转化成分数,但注意,输入的数据还有无限循环的小数,循环节用一对括号包含起来. 之前还没有写过小数转分数的题,当然如果没有循环小数的话,应该比较简单,但是这题 ...

  5. 深度优先搜索(DFS)----------------Tju_Oj_3517The longest athletic track

    这个题主要考察对树的操作,主要思想是DFS或者BFS,其次是找树的直径方法(既要运用两次BFS/DFS),最后作为小白,还练习了vector的操作. DFS框架伪码: bool DSF(Node on ...

  6. CentOs7 Python3安装Openssl以及解决ssl问题

    一.安装OpenssL 1.下载的压缩包放在根目录 wget http://www.openssl.org/source/openssl-1.0.2j.tar.gz 2.在文件夹下解压缩,得到open ...

  7. 关于数据区间变换及numpy数组转图片数据的python实现

    python实现区间转换.numpy图片数据转换 需求: 客户的需求是永无止境的,这不?前几天,用户提出了一个需求,需要将一组数据从一个区间缩放到另一区间? 思路: 先将数据归一化,再乘以对应区间的差 ...

  8. linux服务-ssh

    任务目标:ssh登录,scp上传.下载,ssh秘钥登录, 修改ssh server端的端口为8888然后进行登录和scp测试 使用ssh登陆host1 使用scp下载文件 scp root@192.1 ...

  9. 树形dp(C - Choosing Capital for Treeland CodeForces - 219D )

    题目链接:https://cn.vjudge.net/contest/277955#problem/C 题目大意:输入n,代表有n个城市,然后再输入n-1条有向边,然后让你找出一个改变边数的最小值,使 ...

  10. vi的复制粘贴命令 -- (转)

    vi编辑器有3种模式:命令模式.输入模式.末行模式.掌握这三种模式十分重要: 1.命令模式:vi启动后默认进入的是命令模式,从这个模式使用命令可以切换到另外两种模式,同时无论在任何模式下只要按一下[E ...