POJ 2513Colored Sticks 并查集,字典树

本题综合性很强,用并查集是必须要用路劲压缩查找,其实可以用DFS来判断图的联通性,但肯定没并查集的效率高。字典树我用的是全局变量申请,但要开足够大的空间,开500000RUN ERROR一次,结果开500000*10就A的,而且时间只有 600MS ,字典树也可以动态创建,但时间肯定要多花的,时间空间自己去取舍吧..

 

 

#include <iostream>

using namespace std;

#define  ST_COUNT  500000
struct TNode
{
	int parent;
	int data;
}sn[ST_COUNT];

struct TrieNode
{
	int data;
	int child[26];
}trNode[ST_COUNT*10]; // 字典树节点要开多一点
int tr_index = 1;

int g_NodeId = 0; // 给每一个节点的唯一编号
int NodeDegree[ST_COUNT]; // 存放节点的度

int CreateTrieNode(int inData)
{
	memset(trNode[tr_index].child, 255, sizeof(trNode[tr_index].child) );
	trNode[tr_index].data = inData;
	tr_index++;
	return tr_index-1;
}

int FindAddInsertTrie(char szStr[], int szLen) // 查询字典树,并插入新的节点
{
	int trBase = 0, re, tdata;
	int i;
	for(i = 0; i < szLen; i++)
	{
		if( trNode[trBase].child[szStr[i] - 'a'] == -1 )
		{
			if( szLen-i-1 == 0 ) tdata = g_NodeId++;
			else tdata = -1;
			re = CreateTrieNode(tdata);
			trNode[trBase].child[szStr[i] - 'a'] = re;
			trBase = re;
		}
		else
		{
			trBase = trNode[trBase].child[szStr[i] - 'a'];
		}
	}

	return trNode[trBase].data;
}

int findPEx(int inf) // 路径压缩查找
{
	return sn[inf].parent == -1 ? inf : sn[inf].parent = findPEx(sn[inf].parent);
}

int findP(int inf)
{
	int tf;
	if( sn[inf].parent == -1 )
	{
		return inf;
	}
	else
	{
		tf = findP(sn[inf].parent);
		sn[inf].parent = tf;
		return tf;
	}
}
int main()
{
	// 61088K  594MS 
	freopen("in.txt", "r", stdin);

	int i, j, ta, tb, fa, fb;
	char sza[12], szb[12];
	// 计算节点的度
	// 判断图的联通性
	memset(trNode[0].child, 255, sizeof(trNode[0].child) );
	trNode[0].data = -1;
	memset(NodeDegree, 0, sizeof(NodeDegree) );
	for(i = 0; i < ST_COUNT; i++) sn[i].parent = -1;

	while( scanf("%s", sza) != EOF )
	{
		scanf("%s/n", szb);
		ta = FindAddInsertTrie(sza, strlen(sza) ); // 查找字典树,并插入
		tb = FindAddInsertTrie(szb, strlen(szb) );

		NodeDegree[ta]++; // 计算节点的度
		NodeDegree[tb]++;

		fa = findPEx(ta); // 查找集合
		fb = findPEx(tb);
		if( fa != fb ) // 合并
		{
			sn[fa].parent = fb;
		}
	}

	int odd = 0;
	bool IsLink = true, IsO = true;
	int only = findPEx(0);
	for(i = 1; i < g_NodeId; i++) // 判断图的联通性
	{
		if( only != findPEx(i) )
		{
			IsLink = false;
			break;
		}
	}

	if( IsLink )
	{
		for(i = 0; i < g_NodeId; i++) // 判断欧拉路
		{
			if( NodeDegree[i]%2 != 0 ) odd++;
			if( odd > 2 ) break;
		}
		if( odd > 2 )
			cout<<"Impossible"<<endl;
		else
			cout<<"Possible"<<endl;
	}
	else
		cout<<"Impossible"<<endl;

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值