题目
Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may follow many other users as well. Hence a social network is formed with followers relations. When a user makes a post on Weibo, all his/her followers can view and forward his/her post, which can then be forwarded again by their followers. Now given a social network, you are supposed to calculate the maximum potential amount of forwards for any specific user, assuming that only L levels of indirect followers are counted.
原题目可参见PAT官网甲级题库https://pintia.cn/problem-sets/994805342720868352/problems/994805392092020736
题目大意是求在转发层数上限内消息最多会被多少用户转发。
分析
这道是属于图算法中的遍历操作,遍历操作有两种,一种是深度优先搜索(dfs),另一种是广度优先搜索(bfs),这题有明显的层次需求,所以选择广度为宜。
实现细节
先上参考答案
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int maxv = 1010;
bool inq[maxv] = {false};
struct node
{
int id;
int layer;
};
vector<node> adj[maxv];
int bfs(int s, int L)
{
int num = 0;
queue<node> q;
node start;
start.id = s;
start.layer = 0;
q.push(start);
inq[start.id] = true;
while(!q.empty())
{
node top = q.front();
q.pop();
int u = top.id;
for(int i = 0; i < adj[u].size(); i++)
{
node next = adj[u][i];
next.layer = top.layer + 1;
if(inq[next.id] == false && next.layer <= L)
{
q.push(next);
inq[next.id] = true;
num++;
}
}
}
return num;
}
int main()
{
int n, L; scanf("%d%d", &n, &L);
node user;
for(int i = 1; i <= n; i++)
{
user.id = i;
int idfollow, follownum;
scanf("%d", &follownum);
for(int j = 0; j < follownum; j++)
{
scanf("%d", &idfollow);
adj[idfollow].push_back(user);
}
}
int numquestion; scanf("%d", &numquestion);
for(int i = 0; i < numquestion; i++)
{
memset(inq, false, sizeof(inq));
int s; scanf("%d", &s);
int num = bfs(s, L);
printf("%d\n", num);
}
return 0;
}
再总结一下,图的广度优先搜索模板分两种:
- 邻接矩阵版:
int n, G[maxv][maxv];
bool inq[maxv] = {false};
void bfs(int u)
{
queue<int> q;
q.push(u);
inq[u] = true;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int v = 0; v < n; v++)
{
if(inq[v] == false && G[u][v] != INF)
{
q.push(v);
inq[v] = true;
}
}
}
}
- 邻接表版
vector<int> adj[maxv];
int n;
bool inq[maxv] = false;
void bfs(int u)
差不多类似啦我偷懒了
。。。
关于这道题,主要的感悟如下:
1.一定要弄清楚邻接表的实现方式,当使用vector时,要清楚有向边的方向是怎样的,到底是通过谁到谁(如A到B),这样就能清楚是A的push_back B
2. bfs 总结就是三步走,一建立队列,二塞第一个点进去后进入循环,三循环里取出队首并把满足条件的队首的下层加入队列。
3. 原来memset是cstring才有的哈哈哈