我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805392092020736
题目描述:
题目翻译:
1076 微博转发
众所周知,微博是中国版的推特。微博上的一个用户可能有很多的关注者,同样也可以关注其他许多人。因此,一张社交网络就由关注与被关注的联系所形成。一旦用户在微博上发了一条信息,他/她的所有关注者都可以查看并转发这条信息,同样这条信息能再次被转发者的关注者所再次转发。现在考虑一个社交网络,假设只考虑L层的间接转发者,你需要计算出所有用户所发信息的最大可能转发量。
输入格式:
每个输入文件包含一个测试用例。在每个测试用例中,第一行包含两个正整数:N(<= 1000),用户总数;L,需要考虑的间接转发者的最大层数。这里我们假设所有的用户都被标记为1~N。接下来的N行格式如下:
M[i] user_list[i]
这里M[i](<= 100)是用户user[i]关注的总人数;user_list[i]是M[i]个被用户user[i]所关注的编号。题目保证自己不能关注自己。所有的数字被一个空格分隔。
最后一行给出了一个正整数K,后面跟着K个需要查询的用户ID。
输出格式:
对每一个用户ID,你需要在1行中打印出这个用户的一条信息所能触发的最大转发量。这里我们假设所有人一看到这条信息就会立刻转发,且只考虑L层之内的间接转发者。
输入样例:
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6
输出样例:
4
5
知识点:图的广度优先遍历
思路:图的广度优先遍历
注意点:
(1)用户的编号为1~N,而不是从0开始。
(2)由于可能形成环,必须控制每个用户只能转发消息1次(即遍历时只能访问1次)。
步骤如下述所示:
(1)首先考虑如何建图。由于题目给定的数据是用户关注的情况(而不是被关注的情况),因此如果用户X关注了用户Y,则需要建立由Y指向X的有向边,来表示Y发布的消息可以传递到X并被X转发。
(2)在建图完毕后,使用BFS得到需要的结果。将节点编号和层号建立成结构体,然后控制遍历层数不超过L。
C++代码:
#include<iostream>
#include<queue>
using namespace std;
//用一个节点来将层级信息和节点编号信息封装在一起
struct node{
int number;
int level;
node(int _number, int _level) : number(_number), level(_level) {} //构造函数
};
int n; //用户总数
int l; //需要考虑的转发层数
int graph[2001][2001] = {0}; //有向图,0代表两者之间被有关注与被关注的关系,graph[i][j] = 1表示用户j关注了用户i
void bfs(int nowVisit, int& count);
int main(){
cin >> n >> l;
int m, f; //一个人的关注数m,被关注的人f
for(int i = 0; i < n; i++){
cin >> m;
for(int j = 0; j < m; j++){
cin >> f;
graph[f - 1][i] = 1;
}
}
int k;
cin >> k;
int query;
for(int i = 0; i < k; i++){
cin >> query;
int count = 0;
bfs(query - 1, count);
cout << count << endl;
}
return 0;
}
void bfs(int nowVisit, int& count){
bool visited[2001] = {false}; //标记数组,标记某节点是否已被访问
queue<node> q;
q.push(node(nowVisit, 0));
visited[nowVisit] = true;
while(!q.empty()){
node u = q.front();
q.pop();
for(int i = 0; i < 2001; i++){
if(!visited[i] && graph[u.number][i] != 0){
q.push(node(i, u.level + 1));
if(u.level + 1 <= l){
count++;
}
visited[i] = true;
}
}
}
}
C++解题报告: