智能护理中心系统将辖下的护理点分属若干个大区,例如华东区、华北区等;每个大区又分若干个省来进行管理;省又分市,等等。我们将所有这些有管理或护理功能的单位称为“管理结点”。现在已知每位老人由唯一的一个管理结点负责,每个管理结点属于唯一的上级管理结点管辖。你需要实现一个功能,来统计任何一个管理结点所负责照看的老人的数量。
注意这是一个动态问题,即随时可能有老人加入某个管理结点,并且老人是有可能从一个管理结点换到另一个管理结点去的。
输入格式:
输入在第一行中给出 2 个正整数:N(≤104)是老人的总数量,即老人们从 1 到 N 编号;M(≤105)是归属关系的总数。
接下来是 M 行,每行给出一对归属关系,格式为:
A B
表示 A
归属于 B
。A
或 B
如果是某个管理结点,则用不超过 4 个大写英文字母表示其名称;如果是某位老人,则用老人的编号表示。这里每个 A
保证只有唯一的上级归属 B
,且只有这个中心系统本身是没有上级归属的。此外,输入保证没有老人自己承担管理结点的角色,即 B
一定是一个管理结点,不可能是老人的编号。但一个管理结点既可以管辖下级结点,也可以直接护理一部分老人。
随后每行给出一个指令,格式为:
指令 内容
如果 指令
为 T
,则表示有老人要入院或转院,内容
是某老人的编号和要去的管理结点的名称,以空格分隔;如果 指令
为 Q
,则 内容
是一个管理结点的名称,意思是统计这个结点所负责照看的老人的数量;如果 指令
为 E
,则表示输入结束。题目保证指令总数不会超过 100 个。
输出格式:
对每个 T
指令,将对应的老人转存到对应的管理结点名下;对每个 Q
指令,在一行中输出对应管理结点所负责照看的老人的数量。读到 E
指令就结束程序。
输入样例:
10 23
EAST CNTR
ZJ EAST
SD EAST
WEST CNTR
SX WEST
HZ ZJ
JN SD
2 JN
8 JTH
6 XAHP
4 ZDYH
5 ZDYH
ZDYH HZ
HUZ ZJ
JX ZJ
1 JX
3 JN
WZ ZJ
XAHP XIAN
XIAN SX
YL SX
JTH XIAN
7 XAHP
Q EAST
T 1 YL
Q EAST
Q SX
T 8 ZDYH
Q HZ
Q HUZ
T 10 XAHP
Q CNTR
E
输出样例:
5
4
4
3
0
9
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int maxn = 2e5 + 5;
map<string, int> mp; // 用于将字符串映射为数字的映射表
int index = 1; // 全局唯一的数字标识索引
// 获取字符串对应的数字标识
int get(string s) {
if (mp[s]) {
return mp[s];
} else {
mp[s] = index++;
return mp[s];
}
}
int N, M;
int peo[maxn]; // peo[i] 记录编号为i的管理节点的老人数量
vector<int> G[maxn]; // 邻接表表示图
int fa[maxn]; // 记录每位老人所在的管理节点
// 递归计算以pos为根的子树中老人的总数量
int dfs(int pos) {
int res = peo[pos];
for (auto u : G[pos]) {
res += dfs(u);
}
return res;
}
int main() {
cin >> N >> M;
while (M--) {
string a, b;
cin >> a >> b;
int x = get(a);
int y = get(b);
if (a[0] >= '0' && a[0] <= '9') {
// 如果a是老人编号,则更新老人所在管理节点的老人数量,同时记录老人所在的管理节点
peo[y]++;
fa[x] = y;
} else {
// 如果a是管理节点名称,则在图中添加边,表示y管理x
G[y].push_back(x);
}
}
char opt;
while (cin >> opt) {
if (opt == 'E') break;
string w, des;
if (opt == 'Q') {
// 查询操作
cin >> w;
int res = dfs(get(w));
cout << res << "\n";
} else if (opt == 'T') {
// 转移老人操作
cin >> w >> des;
int id = get(w);
int dd = get(des);
// 更新老人所在的管理节点的老人数量
peo[fa[id]]--; // 老人从原管理节点转出
fa[id] = dd; // 更新老人所在的管理节点
peo[dd]++; // 老人转入新管理节点
}
}
return 0;
}