蒜头最近在沉迷小说,尤其是人物关系复杂的言情小说。它看到的人物关系描述得很的麻烦的时候觉得非常蒜疼,尤其是任务关系里有冗余的时候。什么是冗余关系呢?
这篇小说里有n句描述人物关系的句子,描述了n个人的关系。
每条句子的定义是这样的:
X<->Y 它的意思是:X认识Y,Y也认识X
我们认为小说中的人物关系是具有传递性的,假如A认识B,B认识C,则A也认识C。
冗余关系的定义:就是即使没有这条人物关系,原来的人物之间的所有关系也照样成立。
比如:
小说中已经提到了A认识B,B也认识C。在此之后再讲A认识C就是一个冗余的关系。
小蒜头想求出一共有多少条冗余关系,你能帮帮它吗?
输入格式:
第一行两个整数,表示句子数量n(1<=n<=1000),表示人数m(1<=m<=1000)。
接下来n行,每行两个数,表示一组人物关系。
输出格式:
一个整数,表示冗余关系的数目。
样例输入复制
3 3
1 2
1 3
2 3
样例输出复制
1
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
//根据题目要求m的范围
const int N = 10000;
//father代表父节点 ranki用于判断集合的秩(大小)用于合并
int father[N];
int ranki[N];
//判断 返回元素所在集合的最高父节点
int find(int x){
return father[x] == x?x:father[x] = find(father[x]);
}
int getAnswer(int n,int m,vector<int> A,vector<int> B){
int sum = 0;//用于计算冗余
for(int i = 1;i <= m;i++){
father[i] = i;//首先父节点等于自己
ranki[i] = 1;//开始集合的大小都为1
}
for(int i = 0;i < n;i++){
//寻找A[i] 和 B[i] 的最高父节点
int setA = find(A[i]);
int setB = find(B[i]);
if(setA == setB)sum++;
else{
if(ranki[setA] >= ranki[setB]){
//将B[i] 所在的集合合并到 A[i]所在的集合并以A[i]作为父节点
father[setB] = setA;
//集合元素数量相加
if(ranki[setA] == ranki[setB])
ranki[setA]++;
}else {
father[setA] = setB;
}
}
}
return sum;
}
int main(int argc, char const *argv[]) {
//n 表示关系数
//m 表示人数
int n,m;
scanf("%d%d",&n,&m);
//A、B分别代表关系前后的两个个体
vector<int> A,B;
for(int i = 0;i < n;i++){
int ai,bi;
scanf("%d%d",&ai,&bi);
A.push_back(ai);
B.push_back(bi);
}
printf("%d",getAnswer(n,m,A,B));
return 0;
}