2024年4月10日-暑期实习-第二题(200分)-相似度计算

在线评测链接

题目描述

塔子哥想要处理一批图片,将相似的图片分类。他首先对图片的特征采样,得到图片之间的相似度,然后按照以下规则判断图片是否可以归为一类:
1)相似度>0表示两张图片相似;
2)如果A和B相似,B和C相似,但A和C不相似。那么认为A和C间接相似,可以把ABC归为一类,但不计算AC的相似度:
3)如果A和所有其他图片都不相似,则A自己归为一类,相似度为0。给定一个大小为 N × N N\times N N×N的矩阵 M M M存储任意两张图片的相似度,M]即为第 i i i个图片和第 j j j个图片的相似度,请按照"从大到小"的顺序返回每个相似类中所有图片的相似度之和。

输入描述

第一行一个数 N ( 1 ≤ N ≤ 900 ) N(1\le N\le 900) N(1N900),代表矩阵 M M M中有 N N N个图片。下面跟着 N N N行,每行有 N N N列数据,空格分隔(为了显示整齐,空格可能为多个),代表 N N N个图片之间的相似度。

其中 0 ≤ M [ i ] [ j ] ≤ 100 0\le M[i][j]\le 100 0M[i][j]100,输入保证 M [ i ] [ j ] = M [ j ] [ i ] M[i][j]=M[j][i] M[i][j]=M[j][i]

输入的矩阵分隔符为1个或多个连续空格

输出描述

每个相似类的相似度之和。格式为:一行数字,分隔符为1个空格

样例1

输入

5
0 0 50 0 0
0 0 0 25 0
50 0 0 0 15
0 25 0 0 0
0 0 15 0 0

输出

65 25

说明

把1~5看成A,B,C,D,E
矩阵显示,A和C相似度为50,C和E的相似度为15:B和D相似度为25。划分出2个相似类,分别为
1.{A,C,E},相似度之和为65
2.{B,D},相似度之和25
排序输出相似度之和,结果为:65 25

并查集

题意需要将相似的图片归为一类,很容易想到是并查集的解法,并查集也有路径压缩的方法,所以可以将相似度的和都存在集合的根节点上。

将所有相似的图片归类到一个集合中,并对图片矩阵 a a a进行遍历,如果 a i , j ! = 0 a_{i,j}!=0 ai,j!=0,那么就获取其所在集合的根节点 f a fa fa,使 a n s [ f a ] + = a [ i ] [ j ] ans[fa]+=a[i][j] ans[fa]+=a[i][j]。为了防止重复计算,令 a [ i ] [ j ] = a [ j ] [ i ] = 0 a[i][j]=a[j][i]=0 a[i][j]=a[j][i]=0

最后对 a n s ans ans进行排序,再倒序输出即可。

代码

C++

#include <bits/stdc++.h>
using namespace std;

int n;
int a[1000][1000];
int fa[1000];
int ans[1000];

int find(int x){
	return x==fa[x] ? x:fa[x]=find(fa[x]);
}

int main(){
	std::ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;++i){
		fa[i]=i;
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			cin>>a[i][j];
			if(a[i][j]!=0){
				int fax=find(i),fay=find(j);
				if(fax==fay) continue;
				fa[fax]=fay;
			}
		}
	}
	int res=0;
	for(int i=1;i<=n;++i){
		if(fa[i]==i) res++;
		for(int j=1;j<=n;++j){
			int fax=find(i),fay=find(j);
			if(a[i][j]&&fax==fay){
				ans[fax]+=a[i][j];
				a[i][j]=0;
				a[j][i]=0;
			}
		}
	}
	sort(ans+1,ans+n+1);
	for(int i=n;i>n-res;--i){
		if(ans[i]<=0) break;
		cout<<ans[i]<<" ";
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

塔子哥学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值