Kai’blog

主博客 | 势利纷华,近之而不染者洁,不近者亦洁,君子不立危墙之下。

P1955【绿】

这道题是标准的“离散化+并查集”模版题,通过这道题彻底理解了并查集,同时还意识到了我之前一直用map来实现离散化的方法其实是最简单但是最慢的方法,以这道题为例,map导致时间消耗有点大,不吸氧只有70分,吸氧后才能AC。
大体总结了一下,离散化有三种方式
1.直接用map来实现,最简单但是最慢
2.用自己写的HASH函数来实现,最麻烦但是最快
3.去重后排序,并用手写二分查找或lower_bound来获取索引。这个方法不快不慢不简单不复杂,适中。
以后要学习一下后两个方案

后续

我在做另一道橙色离散化模版题时无意间知道了unordered_map的存在,这是c++11标准引入的一个基于hash的新map,直接把查找的时间复杂度从O(logn)降低到了O(1),我在源代码的map前加了一个unordered_就直接能在不吸氧的情况下AC了!!!太妙了,这意味着我无需学习hash表就可以使用hash表!!!不过需要注意必须是c++11标准才可以使用,以及还需要注意头文件是unordered_map而不是map!

需要吸氧的Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

struct DSUs//这不是一个并查集,这是一个元素离散化的不相交集合的集合,即DSUs
{
	private:
	map<int,int> f;
	map<int,int> d;
	inline void insert(int a){if(f.find(a)==f.end())f[a]=a,d[a]=1;}//私有动态初始化函数,不应该被外部访问
	
	public:
	DSUs(){}
	void merge(int a,int b)
	{
		insert(a);insert(b);
		int A=find(a),B=find(b);
		if(A!=B)
		{
			if(d[A]>=d[B])f[B]=A;
			else f[A]=B;
			if(d[A]==d[B])d[A]++;
		}
	}
	inline int find(int a)
	{
		insert(a);
		if(f[a]==a)return a;
		else
		{
			f[a]=find(f[a]);
			return f[a];
		}
	}
	inline void clear()
	{
		f.clear();
		d.clear();
	}
};
DSUs uf;

int n,a[1000000+5],b[1000000+5],c[1000000+5];
int main()
{
	int t;
	std::ios::sync_with_stdio(false);	std::cin.tie(0); 
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>n;
		for(int j=1;j<=n;j++)
		{
			cin>>a[j]>>b[j]>>c[j];
		}
		for(int j=1;j<=n;j++)
			if(c[j]==1)
				uf.merge(a[j],b[j]);
		int flag=1;
		for(int j=1;j<=n;j++)
		{
			if(c[j]==0)
			{
				if(uf.find(a[j])==uf.find(b[j]))
				{
					flag=0;
					break;
				}
			}
		}
		if(flag==1)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
		uf.clear();
	}
    return 0;
}

无需吸氧的AC-Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <unordered_map>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

struct DSUs//这不是一个并查集,这是一个元素离散化的不相交集合的集合,即DSUs
{
	private:
	unordered_map<int,int> f;
	unordered_map<int,int> d;
	inline void insert(int a){if(f.find(a)==f.end())f[a]=a,d[a]=1;}//私有动态初始化函数,不应该被外部访问
	
	public:
	DSUs(){}
	void merge(int a,int b)
	{
		insert(a);insert(b);
		int A=find(a),B=find(b);
		if(A!=B)
		{
			if(d[A]>=d[B])f[B]=A;
			else f[A]=B;
			if(d[A]==d[B])d[A]++;
		}
	}
	inline int find(int a)
	{
		insert(a);
		if(f[a]==a)return a;
		else
		{
			f[a]=find(f[a]);
			return f[a];
		}
	}
	inline void clear()
	{
		f.clear();
		d.clear();
	}
};
DSUs uf;

int n,a[1000000+5],b[1000000+5],c[1000000+5];
int main()
{
	int t;
	std::ios::sync_with_stdio(false);	std::cin.tie(0); 
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>n;
		for(int j=1;j<=n;j++)
			cin>>a[j]>>b[j]>>c[j];
		for(int j=1;j<=n;j++)
			if(c[j]==1)
				uf.merge(a[j],b[j]);
		int flag=1;
		for(int j=1;j<=n;j++)
		{
			if(c[j]==0)
			{
				if(uf.find(a[j])==uf.find(b[j]))
				{
					flag=0;
					break;
				}
			}
		}
		if(flag==1)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
		uf.clear();
	}
    return 0;
}
posted @ 2023-11-01 14:28  Kai-G  阅读(3)  评论(0编辑  收藏  举报
Copyright © 2019-2020 拱垲. All rights reserved.