qiukeqi

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

种类并查集

简述

一种在循环对称结构中查找同类的数据结构。(或者说对抗关系,且总种类之中的对抗关系是循环的,如下图所示)
(有点像有向循环图)
程序实现要点:
维护大小为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;
}
posted on 2022-08-10 15:00  qiukeqi  阅读(13)  评论(0)    收藏  举报