开始用普通的并查集,一直TLE,后来看到大牛的代码,领悟到可以在findset函数被执行的过程中进一步压缩路径,这样的话下次如果执行findset时同样的路径会快很多,因为上次走同样路劲的时候已经把“长链”拉直了。

还有大牛说需要离散化,能够达到优化,这里没有采用。


//模板开始
#include <string>   
#include <vector>   
#include <algorithm>   
#include <iostream>   
#include <sstream>   
#include <fstream>   
#include <map>   
#include <set>   
#include <cstdio>   
#include <cmath>   
#include <cstdlib>   
#include <ctime>
#include<iomanip>
#include<string.h>
#define SZ(x) (int(x.size()))
using namespace std;

int toInt(string s){
	istringstream sin(s); 
	int t; 
	sin>>t; 
	return t;
}
template<class T> string toString(T x){
	ostringstream sout; 
	sout<<x; 
	return sout.str();
}
typedef long long int64;
int64 toInt64(string s){
	istringstream sin(s); 
	int64 t; 
	sin>>t;
	return t;
}
template<class T> T gcd(T a, T b){ 
	if(a<0) 
		return gcd(-a, b);
	if(b<0) 
		return gcd(a, -b);
	return (b == 0)? a : gcd(b, a % b);
}
//模板结束(通用部分)

#define ifs cin


#define MAX_SIZE 10000005
int next_node[MAX_SIZE];		//存储边
//int in[MAX_SIZE];		//存储节点的入度
//int out[MAX_SIZE];		//存储节点的出度
//int flag[MAX_SIZE];		//标记节点是否存在
int tongji[MAX_SIZE];		//以下标对应结点为代表元的集合的元素个数统计(实际上只是更新了新的代表元的信息,最后可以通过遍历得到其中值个数最大的一个)
int max_tongji;

//void init()		//初始化
//{
//	for(int i = 0; i < MAX_SIZE; i++)
//	{
//		next_node[i] = i;
//	}
//	//memset(in, 0, sizeof(in));
//	//memset(out, 0, sizeof(out));
//	memset(flag, 0, sizeof(flag));
//}

void init_advance()		//初始化
{
	for(int i = 0; i < MAX_SIZE; i++)
	{
		next_node[i] = i;
	}
	//memset(in, 0, sizeof(in));
	//memset(out, 0, sizeof(out));
	//memset(flag, 0, sizeof(flag));
	for(int i = 0; i < MAX_SIZE; i++)
	{
		tongji[i] = 1;
	}

	max_tongji = 1;
}

int findset(int v)		//找元素所在集合的代表元(因为用了路径压缩,路径压缩的主要目的是为了尽快的确定元素所在的集合)
{
	int t1,t2=v;
	while(v!=next_node[v])
		v=next_node[v];
	while(t2!=next_node[t2])		//这里优化的思路还是路径压缩(进一步的在查找函数执行的过程中压缩路径),很神奇!
	{
		t1=next_node[t2];
		next_node[t2]=v;
		t2=t1;
	}
	return v;
}

//void union_nodes(int a, int b)		//集合合并
//{
//	int a1 = findset(a);
//	int b1 = findset(b);
//	next_node[a1] = b1;
//}

void union_nodes_advance(int a, int b)		//集合合并
{
	int a1 = findset(a);
	int b1 = findset(b);
	if(a1 != b1)
	{
		tongji[b1] += tongji[a1];
		if(tongji[b1] > max_tongji)
		{
			max_tongji = tongji[b1];
		}
	}
	next_node[a1] = b1;
}

//【图论05】并查集 1005 More is better

int main()
{
	//ifstream ifs("shuju.txt", ios::in);
	int m, n;
	int cases;
	while(~scanf("%d", &cases))
	{
		init_advance();
		for(int i = 0; i < cases; i++)
		{
			scanf("%d%d", &m, &n);
			union_nodes_advance(m, n);
			//flag[m]++;
			//flag[n]++;
		}

		//int max_tongji = tongji[0];
		//for(int i = 1; i < MAX_SIZE; i++)
		//{
		//	if(tongji[i] > max_tongji)
		//	{
		//		max_tongji = tongji[i];
		//	}
		//}
		printf("%d\n", max_tongji);
	}

	return 0;
}


Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐