本题的算法标签是「模拟」,本质是在一张有向图上模拟消息的洪水填充(Flood Fill / BFS):把每个用户看成一个点,把「用户 i 的转发名单」看成从 i 出发的若干条有向边——forwardLists[i] 的第 j 位为 1,就有一条边 i→j。消息从初始发送者出发,沿有向边不断扩散,因此
答案 = 从
initialSenders中的每个用户出发、沿有向边能走到的所有用户(初始发送者自身也算收到)。
用二进制位表示集合(bitset)。 因为 N≤16,可以把「已收到消息的用户集合」直接压进一个整数的低 N 位,位运算就是集合运算:
mask = (1 << N) - 1:只保留 0∼N−1 号用户的位;在一个社交网络中,有 N 个用户(编号 0 到 N−1)。每个用户都有一个「转发名单」,用一个整数表示:该整数二进制格式中的第 j 位(最低位为第 0 位)为 1,表示这个用户会把消息转发给用户 j。
给定一个整数数组 forwardLists 和一个整数 initialSenders:
forwardLists[i] 是用户 i 的转发名单;initialSenders 的二进制第 j 位为 1,表示用户 j 是初始发送者(初始发送者视为已收到消息);请计算有哪些用户收到了消息,把答案也编码成一个整数返回:其二进制第 i 位为 1 表示用户 i 收到了消息。
例如用户 0、1 都收到了消息,即二进制 0011,返回 3。
注意:N 不固定为 16,而是等于 forwardLists 的长度;用户编号只有 0∼N−1,更高位一律视为 0。
输入只有一行,形如:
[f0, f1, ..., f(N-1)],initialSenders
即先用方括号包住整个转发名单数组,元素之间用半角逗号分隔;方括号之后紧跟一个半角逗号,再给出整数 initialSenders。
逗号之后可能带有空格(本题三个样例在数组内的逗号后都带一个空格,例如 [2, 4, 0],1),你的读入代码需要容忍任意多余空白。
取值范围:
forwardLists 的长度(即用户个数);数据保证 forwardLists[i] 与 initialSenders 只会在第 0∼N−1 位上出现 1(不会出现超出用户编号范围的位)。
输出一行一个十进制整数 ans,其二进制第 i 位为 1 表示用户 i 收到了消息;若没有任何用户收到消息则输出 0。
输入
[2, 4, 0],1
输出
7
说明
forwardLists[0] = 2(二进制 0010):用户 0 转发给用户 1;forwardLists[1] = 4(二进制 0100):用户 1 转发给用户 2;forwardLists[2] = 0(二进制 0000):用户 2 不转发;initialSenders = 1(二进制 0001):用户 0 是初始发送者。转发过程:初始用户 0 收到消息(receivers = 1)→ 第 1 轮用户 0 转发给用户 1(receivers = 3)→ 第 2 轮用户 1 转发给用户 2(receivers = 7)→ 用户 2 不转发,结束。
最终用户 0、1、2 收到消息,二进制 0111,输出 7。
输入
[1, 0, 4],2
输出
2
说明
forwardLists[0] = 1(二进制 0001):用户 0 转发给用户 0(自转发);forwardLists[1] = 0(二进制 0000):用户 1 不转发;forwardLists[2] = 4(二进制 0100):用户 2 转发给用户 2(自转发);initialSenders = 2(二进制 0010):用户 1 是初始发送者。用户 1 收到消息后不转发,传播立即结束,只有用户 1 收到消息,二进制 0010,输出 2。
输入
[3, 2, 4],1
输出
3
说明
forwardLists[0] = 3(二进制 0011):用户 0 转发给用户 0、1;forwardLists[1] = 2(二进制 0010):用户 1 转发给用户 1;forwardLists[2] = 4(二进制 0100):用户 2 转发给用户 2;initialSenders = 1(二进制 0001):用户 0 是初始发送者。第 1 轮用户 0 转发给用户 0、1(receivers = 3);第 2 轮用户 1 只转发给自己,没有新用户收到消息,结束。最终用户 0、1 收到消息,二进制 0011,输出 3。
Scan the QR code below with WeChat to sign in
设置一个用户名,下一步用微信扫码完成注册
请使用微信扫描下方二维码完成注册