【PAT】A1107 Social Clusters ***

本文介绍了一种使用并查集算法解决社交网络中寻找共同兴趣群体的问题。通过输入人们的兴趣列表,算法能有效地找出所有具有相同兴趣爱好的社交集群,并统计各集群的人数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

When register on a social network, you are always asked to specify your hobbies in order to find some potential friends with the same hobbies. A social cluster is a set of people who have some of their hobbies in common. You are supposed to find all the clusters.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤1000), the total number of people in a social network. Hence the people are numbered from 1 to N. Then N lines follow, each gives the hobby list of a person in the format:

K​i​​: h​i​​[1] h​i​​[2] ... h​i​​[K​i​​]

where K​i​​ (>0) is the number of hobbies, and h​i​​[j] is the index of the j-th hobby, which is an integer in [1, 1000].

Output Specification:

For each case, print in one line the total number of clusters in the network. Then in the second line, print the numbers of people in the clusters in non-increasing order. The numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4

Sample Output:

3
4 3 1

总结:并查集的套路 

代码:

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N=1010;
int course[N]={0}; //喜好 
int isRoot[N]={0};  //记录每个节点是否作为某个节点的根结点 
int father[N];

void init(int n){
	for(int i=1;i<=n;i++){
		father[i]=i;  //自成节点 
		isRoot[i]=0;
	}
} 

bool cmp(int a,int b){
	return a>b;
}
int findFather(int x){
	int a=x;
	while(x!=father[x]){
		x=father[x];
	}
	
	while(a!=father[a]){  //压缩路径 
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
} 
void Union(int a,int b){
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB){
		father[faA]=faB;
	}
} 
int main(){
	int n,total,k;
	scanf("%d",&n);
	init(n);  //初始化 
	for(int i=1;i<=n;i++){
		scanf("%d:",&total);
		for(int j=0;j<total;j++){
			scanf("%d",&k);
			if(course[k]==0){  //h没有人喜欢过 
				course[k]=i;  //根结点 
			}
			Union(i,findFather(course[k]));  //合并 *
		}
		
	}
	 
	for(int i=1;i<=n;i++){
		isRoot[findFather(i)]++;
	}
	int ans=0; //记录集合数目
	for(int i=1;i<=n;i++){
		if(isRoot[i]!=0){
			ans++;
		}
	}
	printf("%d\n",ans);
	sort(isRoot+1,isRoot+n+1,cmp); //* 
	for(int i=1;i<=ans;i++){
		printf("%d",isRoot[i]);
		if(i<ans) printf(" ");
	}
	return 0;
}

 

### 在无 *MODULE* 标识情况下对 SPEF 数据按 module 分类处理的方法 当 SPEF 文件中未提供显式的 `*MODULE*` 标识时,仍然可以通过间接的方式推断模块边界并对数据进行分类。以下是具体的解决方案: --- #### 1. 基于 Net 名称的模式匹配 尽管 SPEF 文件缺少明确的模块标识符,但通常每条记录都包含与特定信号网络(Net)关联的数据。这些 Net 名称往往遵循一定的命名约定,例如前缀或路径分隔符(如 `/`),可用于区分不同的模块。 ##### 实现思路: - 遍历 SPEF 文件中的每一行。 - 提取所有以 `*NET*` 开头的行及其对应的寄生参数。 - 利用正则表达式分析 Net 名称,识别潜在的模块归属关系。 ```python import re def extract_nets_and_modules(spef_content): net_pattern = r'\*NET\*\s+(.+?)\n' nets = re.findall(net_pattern, spef_content) module_mapping = {} for net_name in nets: # 使用正则表达式解析 Net 名称中的模块信息 match = re.match(r'^(.*?)\/.*$', net_name) # 假设模块名为 Net 名称的第一部分 if match: module_name = match.group(1) else: module_name = "UNKNOWN" # 如果无法解析,则标记为未知模块 if module_name not in module_mapping: module_mapping[module_name] = [] module_mapping[module_name].append(net_name) return module_mapping ``` 上述代码通过正则表达式提取 Net 名称,并尝试从中拆解出模块名[^1]。 --- #### 2. 结合 Verilog/SPICE 网表辅助划分 如果仅依赖 SPEF 文件难以准确定位模块边界,可以借助更高层次的设计文件(如 Verilog 或 SPICE 网表)。这类文件通常明确定义了各个模块及其内部连接关系。 ##### 步骤说明: - 导入对应级别的网表文件。 - 构建从顶层到底层模块的层级映射。 - 将 SPEF 中的 Net 映射回相应的模块。 ```python def map_spef_to_verilog(verilog_file, spef_nets): verilog_hierarchy = {} # 存储模块层级关系 with open(verilog_file, 'r') as file: content = file.read() # 解析 Verilog 文件构建模块层级树 module_pattern = r'module\s+(\w+)\s*\(.*?\);(?:[\s\S]*?endmodule)' matches = re.finditer(module_pattern, content) for match in matches: module_name = match.group(1) verilog_hierarchy[module_name] = [] # 初始化子模块列表 # 假设已知模块间的父子关系... # (此处省略具体实现逻辑) # 将 SPEF Nets 映射至相应模块 mapped_results = {} for net in spef_nets: # 查找所属模块(需额外定义查找规则) pass return mapped_results ``` 此方法利用外部设计文件补充缺失的模块信息[^2]。 --- #### 3. 自动聚类算法推测模块结构 对于完全缺乏上下文线索的情况,还可以考虑运用机器学习技术对 SPEF 数据进行自动聚类。例如,基于电阻、电容等物理特性相似性的 K-Means 方法可以帮助发现隐含的模块分区。 ##### 关键步骤: - 计算各 Net 的特征向量(如总阻抗值、互连长度等)。 - 应用聚类模型将具有相近特性的 Net 归属同一组别。 - 后续手动验证并标注生成的簇作为虚拟模块。 ```python from sklearn.cluster import KMeans import numpy as np def cluster_spef_data(feature_matrix, num_clusters=5): kmeans = KMeans(n_clusters=num_clusters).fit(feature_matrix) labels = kmeans.labels_ clustered_data = {} for i, label in enumerate(labels): if label not in clustered_data: clustered_data[label] = [] clustered_data[label].append(i) # 添加索引位置 return clustered_data ``` 注意:这种方法适用于探索性分析阶段,但可能需要较多人工干预校正结果。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_之桐_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值