Live2D

扩展域并查集

<扩展域并查集真的是个好东西啊qaq

扩展域并查集可以维护多组关系,并且可以不用推像带权并查集那样繁琐的式子,对于博主这种蒟蒻绝对适用
其主要思想是将一个点拆分成好几个点来维护多组关系。

直接讲不是很形象,我们来看一道例题


题目描述

S城现有两座监狱,一共关押着N名罪犯,编号分别为1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c的冲突事件。

每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。

在详细考察了NN 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。

那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?

题目分析:题目要求看到的最大的可能发生的冲突的最小值,所以通过贪心策略我们可知,如果想让尽量可能发生的时间冲突的最大值最小,就要先尽量不让冲突大的事件发生。
所以我们把能冲突的事件的影响值先从大到小排一个序,就先让大的事件不发生,如果到哪一个事件它不可避免的要发生,那答案就是这个事件的影响值。

考虑,如果只有一个监狱的话,那么我们就用普通并查集维护一下会冲突的两个人是否在一个监狱就好,但问题是本题有两个监狱,所以如果给我们一对关系,肯定把其中一个人放在一个监狱,再把另一个人放进另一个监狱,问题是怎么维护呢,我们就用到了扩展域并查集,将一个点拆成两个点即f[i] 与 f[2*i],其中一个维护我朋友所在的集合,另一个维护我敌人所在的集合,每次查询一下我所在的集合与我的敌人所在的集合;再查询一下这对关系的敌人所在的集合,敌人的敌人所在的集合;判断一下如果要让这个事情不发生,我就应该和我的敌人的朋友在一个监狱(因为敌人的敌人是朋友嘛),我的敌人应该和我的 敌人在一个监狱,所以合并一下就好,如果某个事件的查询时,我与我的敌人同属于一个监狱,那么这件事情就不可避免的发生了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 20005

using namespace std;

struct node
{
	int x,y,data;
};
node a[maxn*5];
int f[maxn<<1],n,m;

inline bool cmp(node xx,node yy)
{
	return xx.data>yy.data;
}

inline int find(int k)
{
	if(f[k]==k) return f[k];
	return f[k]=find(f[k]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		f[i]=i; f[i+n]=i+n;
	}
	for(int i=1;i<=m;i++)
	    scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].data);
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int x_friend=find(a[i].x),x_enemy=find(a[i].x+n);
		int y_friend=find(a[i].y),y_enemy=find(a[i].y+n);
		if(x_friend==y_friend)
		{
			printf("%d",a[i].data);
			return 0;
		}
		f[x_friend]=y_enemy;
		f[x_enemy]=y_friend; 
		if(i==m)//如果没有冲突发生就输出0
		{
			printf("0");
			return 0;
		}
	}
	return 0;
}


扩展域并查集适用于有多组关系需要用并查集维护的题目,这类题目只要找准题目中有几组关系,把握住,我的敌人的敌人就是我的朋友的原则(大部分题满足,可能有少部分题不满足这个原则,注意分析。)这类题目不会太难,同时这类题目也都可以用带权并查集来解,看个人觉得哪个实用了,我是用扩展域来解的。


写在最后,祝各位OIER NOIP 2019 RP++ SCORE++

posted @ 2019-08-12 09:22  Hoyoak  阅读(1843)  评论(0编辑  收藏  举报