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. 彻底搞懂 SQLAlchemy中的 backref

    教程源码截取: class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) name = Colum ...

  2. python set() 集合的添加删除、交集、并集、差集、交叉补集、集合的方法介绍以及使用案例

    可变不可变: 1.可变:列表.字典.例如列表类型是可变的,我修改了列表中的元素的值,但是列表本身在内存中的地址是没有变化的,所以列表的元素是可以被改变的 >>> name=[&quo ...

  3. Java基础-面向对象第二特征之继承(Inheritance)

    Java基础-面向对象第二特征之继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承的概述 在现实生活中,继承一般指的是子女继承父辈的财产.在程序 ...

  4. [Java] 理解JVM之二:类加载步骤及内存分配

    一.类加载器 ClassLoader 能根据需要将 class 文件加载到 JVM 中,它使用双亲委托模型,在加载类的时候会判断如果类未被自己加载过,就优先让父加载器加载.另外在使用 instance ...

  5. AAC音频格式详解

    关于AAC音频格式基本情况,可参考维基百科http://en.wikipedia.org/wiki/Advanced_Audio_Coding AAC音频格式分析 AAC音频格式有ADIF和ADTS: ...

  6. Shell记录-Shell脚本基础(四)

    while循环,使您能够重复执行一组命令,直到某些条件发生.它通常用于当你需要反复操纵的变量值. 语法 while command do Statement(s) to be executed if ...

  7. Linux下安装PHP的lua扩展库

    一.安装Lua 5.3.4 下载 http://www.lua.org/ftp/lua-.tar.gz tar xvf lua-.tar.gz cd lua- 重要:进入解压缩后的路径 cd .../ ...

  8. [Luogu 2169] 正则表达式

    [Luogu 2169] 正则表达式 感谢 0xis 推题. 记忆中很久没有过一遍写过一题了- 别被题目名称蒙骗!这不是正则表达式题目!和字符(串)处理一点关系都没有!这是个图论题啊喂! 题都没急,C ...

  9. Java并发编程原理与实战二十三:Condition原理分析

    先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使condit ...

  10. java 去除末尾的零 如果小数点可以去除同时去除小数点

    String s; if(s.indexOf(".") > 0){ //正则表达 s = s.replaceAll("0+?$", "" ...