您的位置:首页 > 其它

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

2013-06-28 20:40 441 查看
开始用普通的并查集,一直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
++;
}

//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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: