文章目录
一、BFS试炼之微博转发
描述
微博上的用户既可能有很多关注者,也可能关注很多其他用户。
因此,形成了一种基于这些关注关系的社交网络。
当用户在微博上发布帖子时,他/她的所有关注者都可以查看并转发他/她的帖子,然后这些人的关注者可以对内容再次转发…
现在给定一个社交网络,假设只考虑L层关注者,请你计算某些用户的帖子的最大可能转发量。
补充
如果B是A的关注者,C是B的关注者,那么AA的第一层关注者是B,第二层关注者是C。
输入
第一行包含两个整数,N表示用户数量,LL示需要考虑的关注者的层数。
假设,所有的用户的编号为1∼N。
接下来N行,每行包含一个用户的关注信息,格式如下:
M[i] user_list[i]
M[i]是第ii名用户关注的总人数,user_list[i]是第ii名用户关注的M[i]个用户的编号列表。
最后一行首先包含一个整数K,表示询问次数,然后包含K个用户编号,表示询问这些人的帖子的最大可能转发量。
数据范围
1≤N≤1000,
1≤L≤6,
1≤M[i]≤100,
1≤K≤N
输出
按顺序,每行输出一个被询问人的帖子最大可能转发量。
假设每名用户初次看到帖子时,都会转发帖子,只考虑L层关注者。
输入样例 1
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6
输出样例 1
4
5
解题思路:
- 可以转变为,求解一张有向图中,到指定点的距离 ≤ \leq ≤L的点的个数。即用BFS来遍历图
- 若A关注了B,则B的帖子可以抵达A,A可以转发B的帖子。创建<B,A>边
- 用链式前向星创建图
代码实现:
#include<iostream>
#include<queue>
#include<string.h>
#define MaxSize 1050
using namespace std;
int N, L, K;
//无权值的链式前向星
typedef struct Edge {
int to,next;
} Edge;
int tot;
int head[MaxSize];//head[i],第i个点的第一个孩子结点的索引
Edge edge[MaxSize];
//加边函数
void add_edge(int u, int v) {
//u为起点,v为终点,w为权值
edge[tot].to = v; //tot为空结点指针
edge[tot].next = head[u];
head[u] = tot++;//tot为任一个未被使用的空节点指针。
}
int BFS(int num) {
int sum = 0;
int flag[MaxSize] = {
0};//标记已满足要求的点
flag[num]=1;
queue<int> q;
for (int i = head[num]; i != -1; i = edge[i].next) {
q.push(edge[i].to);
flag[edge[i].to] = 1;
sum++;
}
for (int i = 2; i <= L; i++) {
int Q_size = q.size();//存每一层的大小
while (Q_size--) {
int t = q.front();//取栈顶
q.pop();
for (int j = head[t]; j != -1; j = edge[j].next) {
if (flag[edge[j].to] != 1) {
//若未取过
q.push(edge[j].to);
flag[edge[j].to] = 1;
sum++;
}
}
}
}
return sum;
}
int main() {
cin >> N >> L;
memset(head, -1, sizeof head);
//输入数据
int x, y;
for (int i = 1; i <= N; i++) {
cin >> x;
for (int j = 0; j < x; j++) {
cin >> y;
add_edge(y, i);
}
}
//查看图的建立是否正确
// for (int i = 1; i <= MaxSize; i++) { //从1开始
// for (int j = head[i]; j != -1; j = edge[j].next) {
// printf("结点%d->结点%d\n", i, edge[j].to);
// }
// }
//咨询K个人的转发量
cin >> K;
int num;
while (K--) {
cin >> num;
cout << BFS(num)<<endl;
}
}
二、DFS试炼之不同路径数
描述
给定一个n×m的二维矩阵,其中的每个元素都是一个[1,9]之间的正整数。
从矩阵中的任意位置出发,每次可以沿上下左右四个方向前进一步,走过的位置可以重复走。
走了k次后,经过的元素会构成一个(k+1)位数。
请求出一共可以走出多少个不同的(k+1)位数。
输入
第一行包含三个整数n,m,k。
接下来n行,每行包含m个空格隔开的整数,表示给定矩阵。
数据范围
1≤n,m≤5,
0≤k≤5,
m×n>1
输出
输出一个整数,表示可以走出的不同(k+1)位数的个数。
输入样例 1
3 3 2
1 1 1
1 1 1
2 1 1
输出样例 1
5
解题思路:
- 根据题意,可以用DFS遍历得到,从[x,y]出发走k步的每一种情况
- 将每种情况存入set集合即可自动去重
- 注意:每一步不能同时走x,y
代码实现:
#include<iostream>
#include<set>
using namespace std;
set<int> s;
int n, m, k;
int Arr[10][10];
int dx[4] = {
-1, 0, 1, 0}, dy[4] = {
0, 1, 0,-1};//一次走一步,走x不走y
void dfs(int x, int y, int q, int value) {
//第q步的横坐标x,纵坐标y,当前值value
if (q == k) {
//若为第k步,将当前值加入set
s.insert(value);
return ;
}
for (int i = 0; i < 4; i++) {
int xx = x + dx[i];
int yy = y + dy[i];
if (xx < n && yy < m && xx >= 0 && yy >= 0)
dfs(xx, yy, q + 1, value * 10 + Arr[xx][yy]);
}
}
int main() {
cin

文章介绍了使用BFS解决微博转发的最大可能转发量问题,利用DFS计算不同路径数,应用并查集处理合并集合操作,堆排序求解前k小的数,以及分组背包和最短路Floyd算法解决消防安全指挥问题和铺设光纤问题,最后讨论了多重背包问题及其求解策略。
最低0.47元/天 解锁文章
335

被折叠的 条评论
为什么被折叠?



