用户的影响力定义为:从某个社交网络用户开始,找出所有可以在
k
跳(直接或间接关系)内接触到的其他用户的总个数。
请实现一个程序,计算给定社交网络中某个用户在
k
跳范围内的影响力。
输入描述
第一行输入
N M K
(三个空格分隔的正整数):
N
代表社交网络连接总数,
M
代表需要计算影响力的用户编号,
K
代表计算影响力的范围。
1<=N,K<=1000
,
0<=M<1000
接下来的
N
行,每行两个整数
X Y(0<=X,Y<=1000)
,代表社交网络中一条直接连接的边,如
1 2
代表
1
号与
2
号用户互相直接连接。
用例确保输入有效,无需进行校验
输出描述
输出
M
用户在
k
跳范围内的影响力
示例一
输入
5 0 2 0 1 1 2 2 3 3 4 4 0
输出
4
示例二
输入
8 0 3 0 1 0 2 0 3 3 4 2 5 5 4 2 3 1 5
输出
5
时空限制
时间限制: C/C++ 1000ms, 其他语言:2000ms
内存限制: C/C++ 256MB, 其他语言:512MB
解题思路
本题是一个非常典型的图搜索问题,可以直接将输入转化为邻接表来完成。
类似的题目有LC841. 钥匙和房间
其问题转变为,
从原点
M
出发,距离为
k
的点一共有多少个
?
由于规定了距离
k
,因此应该着重考虑使用BFS来解决问题,而不太适合使用DFS来解决了。
换个表达就是,从原点
M
出发,向外搜索
k
层,一共能够搜索到多少个点?
所以直接套上BFS代码的模板就可以完成。
在每一层的搜索中,
k
都会递减
1
,直到
k
小于
0
停止搜索,完成了
k
层搜索。
有很多人写了DFS版本的代码,这是一种错误的做法。
感兴趣的同学也可以尝试DFS的写法,很容易漏计或者超时。
代码
Python
from collections import defaultdict, deque
# 输入连接数n,起始节点m,步数k n, m, k = map(int, input().split())
# 初始化邻接表 neighbor_dict = defaultdict(list)
# 输入边的情况 for _ in range(n): # 获得某一条无向边的两个节点,a和b a, b = map(int, input().split()) # a的近邻节点包含b,b的近邻节点包含a neighbor_dict[a].append(b) neighbor_dict[b].append(a)
# 输入网格大小n,障碍点个数k n, k = map(int, input().split()) # 构建大小为n*n的网格,初始化其中位置均为0 grid = [[0] * n for _ in range(n)] # 循环k次,输入每一个障碍点的坐标(x, y) for _ in range(k): x, y = map(int, input().split()) # 将障碍点修改为1 grid[x][y] = 1
# 初始化答案 ans = 0 # 递归入口,起始点为(0, 0),填充方块个数num = 0 dfs(grid, 0, 0, n, 0)
print(ans)
Java
import java.util.Scanner;
publicclassMain{
// 根据当前左上角的点(x,y),获得下一个可能的点(nx,ny)的函数 publicstaticint[] getNext(int x, int y, int n) { if (y + 1returnnewint[]{x, y + 1}; } returnnewint[]{x + 1, 0}; }
// 检查以(x, y)为左上角的2*2正方形,能否填充在grid中的函数 publicstaticbooleancheck(int[][] grid, int x, int y, int n){ if (x == n - 1 || y == n - 1) { returnfalse; } return grid[x][y] == 0 && grid[x + 1][y] == 0 && grid[x][y + 1] == 0 && grid[x + 1][y + 1] == 0; }
// 回溯函数 publicstaticvoiddfs(int[][] grid, int cx, int cy, int n, int num){ ans = Math.max(ans, num); if (cx == n - 1) { return; } int[] next = getNext(cx, cy, n); int nx = next[0], ny = next[1];
// 不填充当前点 dfs(grid, nx, ny, n, num);
// 如果可以填充当前点 if (check(grid, cx, cy, n)) { update(grid, cx, cy); dfs(grid, nx, ny, n, num + 1); rollBack(grid, cx, cy); } }
publicstaticvoidmain(String[] args)
{ Scanner scanner = new Scanner(System.in);
// 输入网格大小n,障碍点个数k int n = scanner.nextInt(); int k = scanner.nextInt();
// 构建大小为n*n的网格,初始化其中位置均为0 int[][] grid = newint[n][n]; for (int i = 0; i int x = scanner.nextInt(); int y = scanner.nextInt(); grid[x][y] = 1; // 将障碍点修改为1 }
// 初始化答案 ans = 0;
// 递归入口,起始点为(0, 0),填充方块个数num = 0 dfs(grid, 0, 0, n, 0);
// 输出结果 System.out.println(ans); } }
C++
#include #include usingnamespacestd;
// 根据当前左上角的点(x,y),获得下一个可能的点(nx,ny)的函数 pair<int, int> getNext(int x, int y, int n){ if (y + 1return {x, y + 1}; } return {x + 1, 0}; }
// 检查以(x, y)为左上角的2*2正方形,能否填充在grid中的函数 boolcheck(constvector<vector<int>>& grid, int x, int y, int n){ if (x == n - 1 || y == n - 1) { returnfalse; } return grid[x][y] == 0 && grid[x + 1][y] == 0 && grid[x][y + 1] == 0 && grid[x + 1][y + 1] == 0; }
// 回溯函数 voiddfs(vector<vector<int>>& grid, int cx, int cy, int n, int num){ ans = max(ans, num); if (cx == n - 1) { return; } pair<int, int> next = getNext(cx, cy, n); int nx = next.first, ny = next.second;
// 不填充当前点 dfs(grid, nx, ny, n, num);
// 如果可以填充当前点 if (check(grid, cx, cy, n)) { update(grid, cx, cy); dfs(grid, nx, ny, n, num + 1); rollBack(grid, cx, cy); } }
intmain(){ // 输入网格大小n,障碍点个数k int n, k; cin >> n >> k;
// 构建大小为n*n的网格,初始化其中位置均为0 vector<vector<int>> grid(n, vector<int>(n, 0)); for (int i = 0; i int x, y; cin >> x >> y; grid[x][y] = 1; // 将障碍点修改为1 }
// 初始化答案 ans = 0;
// 递归入口,起始点为(0, 0),填充方块个数num = 0 dfs(grid, 0, 0, n, 0);