2 solutions
-
0
from collections import Counter n,m,k,l = map(int,input().split()) nmap = [[0]*n for _ in range(n)] for _ in range(m): x,y = map(int,input().split()) nmap[x-1][y-1] = 1 nmap[y-1][x-1] = 1 infos = Counter() def dfs(ids,path:list): if len(path)>=2: if path[1]!=k-1: infos.update([path[1]]) return for i in range(n): if nmap[ids][i]==1: path.append(i) dfs(i,path) path.pop() dfs(k-1,[]) for i in range(n): if nmap[k-1][i]: if i in infos: del infos[i] else: if i not in infos: infos[i] = 0 del infos[k-1] results= list(infos.items()) results.sort(key=lambda x:( -x[1],x[0])) results = [each[0]+1 for each in results] results = results[:l] if len(results)<l: results = results + [0]*(l-len(results)) print(" ".join(map(str,results)))
-
0
题面描述:
在这个问题中,我们需要为社交网络平台上的用户提供好友推荐功能。具体而言,输入包括用户总数 (N)、好友关系总数 (M)、待推荐用户编号 (K) 以及需要推荐的好友数量 (L)。随后会有 (M) 行数据,表示用户之间的好友关系。我们需根据用户 (K) 的共同好友数量来计算其与其他用户的相似度,推荐相似度最高的 (L) 个用户,且推荐用户不能是用户 (K) 的好友。推荐结果需按相似度从高到低排序,若相似度相同,则按用户编号从小到大排序。如果找到的候选用户少于 (L) 个,则需要补充与用户 (K) 没有任何共同好友的其他用户,如果仍不足 (L) 个,则用 (0) 补位。通过这个推荐功能,可以帮助用户发现新的好友,增强社交网络的互动。
思路:模拟
题目要求给目标用户推荐好友,首先被推荐对象不能是目标用户的好友。因此我们在读入用户关系时,标记一下与目标用户互为好友的用户。
之后,枚举所有未被标记用户,他们都是待定对象。而与目标用户相似度,就是与其相连的边中,被标记的点的数量。因此统计后再排序即可。
具体步骤如下:
-
数据结构定义:
- 使用一个大小为
maxn
的数组vis
来标记特定用户 (g) 的好友。若用户 (i) 是 (g) 的好友,则vis[i]
为true
。 - 使用邻接表
e
来存储每个用户的好友列表,以便后续快速查找每个用户的好友。
- 使用一个大小为
-
读取输入:
- 首先读取用户总数 (n)、好友关系数 (m)、特定用户编号 (g)、以及要输出的推荐好友数量 (p)。
- 接下来,逐条读取好友关系 (x) 和 (y),并更新邻接表和
vis
数组。若 (x) 或 (y) 是用户 (g),则将其标记为与 (g) 直接相连。
-
计算相似度:
- 遍历所有用户 (i),跳过已标记为与 (g) 相连的用户。
- 对于每个未被标记的用户 (i),计算其与 (g) 的相似度,即其好友中有多少是与 (g) 直接相连的用户。通过一个辅助数组
show
来避免重复计数。
-
记录和排序:
- 将每个用户及其相似度(得分)存储在结构体数组
b
中。记录符合条件的用户数量cnt
。 - 对
b
数组进行排序,首先根据得分从高到低,其次根据用户编号从小到大进行排序。这保证了我们能够优先推荐相似度高的用户。
- 将每个用户及其相似度(得分)存储在结构体数组
-
输出结果:
- 最后输出前 (p) 个得分最高的用户编号。如果得分用户少于 (p) 个,程序可以调整输出,以确保数量符合要求(此题未涉及,代码中未处理,但可根据需求调整)。
代码
java
import java.util.*; public class Main { static final int MAXN = 100010; // 定义最大节点数量为 100010 static int n, m, g, p; // n: 节点数, m: 边数, g: 特定节点, p: 要输出的节点数 static boolean[] vis = new boolean[MAXN]; // 记录特定节点 g 相连的节点 static List<Integer>[] e = new ArrayList[MAXN]; // 邻接表,用于存储图中的边 static int cnt; // 记录符合条件的节点数量 static boolean[] show = new boolean[MAXN]; // 辅助数组,用于记录某个节点的邻居是否已被访问过 static class Node { int id, score; // 节点编号和得分 Node(int id, int score) { this.id = id; this.score = score; } } static Node[] b = new Node[MAXN]; // 存储每个符合条件节点的编号和得分 public static void main(String[] args) { Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); // 读取节点数 m = scanner.nextInt(); // 读取边数 g = scanner.nextInt(); // 读取特定节点 g p = scanner.nextInt(); // 读取要输出的节点数 for (int i = 0; i < MAXN; i++) { e[i] = new ArrayList<>(); // 初始化邻接表 } for (int i = 1; i <= m; ++i) { int x = scanner.nextInt(); // 读取每条边的第一个节点 x int y = scanner.nextInt(); // 读取每条边的第二个节点 y e[x].add(y); // 将 y 加入到 x 的邻接表中 e[y].add(x); // 将 x 加入到 y 的邻接表中 if (x == g || y == g) { // 如果 x 或 y 中有一个是特定节点 g vis[x] = true; // 标记 x 为与 g 相连 vis[y] = true; // 标记 y 为与 g 相连 } } for (int i = 1; i <= n; ++i) { if (vis[i]) continue; // 如果节点 i 与 g 相连,跳过 int score = 0; // 初始化得分为 0 Arrays.fill(show, false); // 重置 show 数组 for (int x : e[i]) { // 遍历节点 i 的所有邻居 if (vis[x] && !show[x]) { // 如果邻居 x 与 g 相连且未被访问过 score += 1; // 增加得分 show[x] = true; // 标记邻居 x 已被访问 } } b[++cnt] = new Node(i, score); // 将节点 i 和其得分记录下来 } Arrays.sort(b, 1, cnt + 1, (x, y) -> { // 根据得分排序,如果得分相同,按节点编号升序排序 if (x.score == y.score) return Integer.compare(x.id, y.id); return Integer.compare(y.score, x.score); }); int outputCount = Math.min(p, cnt); // 计算实际可输出的节点数 for (int i = 1; i <= outputCount; ++i) { System.out.print(b[i].id + " "); // 输出得分最高的节点的编号 } for (int i = outputCount + 1; i <= p; ++i) { System.out.print("0 "); // 如果不足 p 个节点,补充 0 } } }
python
n , m , k , L = map(int, input().split()) edges = [[] for _ in range(n + 1)] # 读入数据 for _ in range(m): x , y = map(int, input().split()) edges[x].append(y) edges[y].append(x) # 去重排序 for i in range(1 , n + 1): edges[i] = list(set(edges[i])) edges[i].sort() # 计算共同好友 def get_commend_friend(x , y): i = 0 ans = 0 st = set(edges[y]) for item in edges[x]: if item in st: ans += 1 return ans # 计算答案 res = [] for i in range(1 , n + 1): # 排除自己 if i == k: continue # 排除已经是好友的 if k in edges[i]: continue # 计算共同好友 res.append([get_commend_friend(k , i) , i]) # 排序输出,注意排序规则:共同好友数目降序,编号升序 res.sort(key = lambda x : (-x[0] , x[1])) ans = [] # 输出答案 for i in range(L): if i < len(res): ans.append(res[i][1]) else: ans.append(0) print(*ans)
C++
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; // 定义最大节点数量为 100010 int n, m, g, p; // n: 节点数, m: 边数, g: 特定节点, p: 要输出的节点数 int vis[maxn]; // 记录特定节点 g 相连的节点 vector<int> e[maxn]; // 邻接表,用于存储图中的边 int cnt; // 记录符合条件的节点数量 bool show[maxn]; // 辅助数组,用于记录某个节点的邻居是否已被访问过 struct node { int id, score; // 节点编号和得分 } b[maxn]; // 存储每个符合条件节点的编号和得分 int main() { std::ios::sync_with_stdio(false); // 提高 cin/cout 的运行效率 cin >> n >> m >> g >> p; // 读取输入的 n, m, g, p 的值 int x, y; for (int i = 1; i <= m; ++i) { cin >> x >> y; // 读取每条边的两个节点 x 和 y e[x].push_back(y); // 将 y 加入到 x 的邻接表中 e[y].push_back(x); // 将 x 加入到 y 的邻接表中 if (x == g || y == g) { // 如果 x 或 y 中有一个是特定节点 g vis[x] = true; // 标记 x 为与 g 相连 vis[y] = true; // 标记 y 为与 g 相连 } } for (int i = 1; i <= n; ++i) { if (vis[i]) continue; // 如果节点 i 与 g 相连,跳过 int score = 0; // 初始化得分为 0 memset(show, 0, sizeof show); // 重置 show 数组 for (auto x : e[i]) { // 遍历节点 i 的所有邻居 if (vis[x] && !show[x]) { // 如果邻居 x 与 g 相连且未被访问过 score += 1; // 增加得分 show[x] = true; // 标记邻居 x 已被访问 } } b[++cnt] = (node){i, score}; // 将节点 i 和其得分记录下来 } sort(b + 1, b + cnt + 1, [&](node x, node y) { // 根据得分排序,如果得分相同,按节点编号升序排序 return x.score == y.score ? x.id < y.id : x.score > y.score; }); for (int i = 1; i <= p; ++i) { cout << b[i].id << " "; // 输出得分最高的 p 个节点的编号 } return 0; }
-
- 1
Information
- ID
- 108
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 5
- Tags
- # Submissions
- 672
- Accepted
- 192
- Uploaded By