种类并查集
简述
一种在循环对称结构中查找同类的数据结构。(或者说对抗关系,且总种类之中的对抗关系是循环的,如下图所示)
(有点像有向循环图)
程序实现要点:
维护大小为m * N的数组,m为种类的数量,N为元素数量,在知道元素x对抗元素y时,merge(x, y + N),merge(x + N, y + 2 * N).....merge(x + (m-1) * N, y)。对任意元素x,y,查询x和y是否有相同的父节点就可知道x和y是否属于同一类。
以下用代码解决 关押罪犯问题。
代码
#include <vector>
#include <iostream>
#include <math.h>
#include <string>
#include <algorithm>
using namespace std;
int cmp(const vector<int>& l,const vector<int>& r){
return l[2] > r[2];
}
int find(vector<int>& fa, int i){
if(fa[i] == i){
return i;
}else{
fa[i] = find(fa,fa[i]);
return fa[i];
}
}
void merge(vector<int>& fa,int i, int j){
fa[find(fa,i)] = find(fa,j);
}
int main()
{
string temp;
cin>>temp;
int peopleNum = stoi(temp);
cin>>temp;
int dataCount = stoi(temp);
vector<vector<int>> relations(dataCount, vector<int>(3));
for(int i = 0; i < dataCount; i++){
for(int j = 0; j < 3; j++){
cin>>temp;
relations[i][j] = stoi(temp);
}
}
sort(relations.begin(), relations.end(), cmp);//将仇恨值从大到小排序
vector<int> fa(peopleNum * 2);
int bufferSize = fa.size();
for(int i = 0; i < bufferSize; i++){//初始化并查集数组,使得每个元素指向自身
fa[i] = i;
}
for(vector<int>& v : relations){//将仇恨关系从大到小依次加入并查集,当发生冲突时,就是仇恨的最小值。
if(find(fa,v[0]-1) == find(fa,v[1]-1)){
cout<<v[2]<<endl;
return 0;
}
//cout<<"asdasd"<<endl;
merge(fa,v[0]-1,v[1]-1 + peopleNum);
merge(fa,v[0]-1 + peopleNum,v[1]-1);
}
cout<<"0"<<endl;
return 1;
}
浙公网安备 33010602011771号