HDU 3635 Dragon Balls 七龙珠 Union Find算法

孙悟空要寻找七龙珠,这回是七龙珠的增强版了,因为这些龙珠会衍生,最后不止七颗龙珠了。

悟空带着布玛的龙珠雷达探测器出发了,却发现布玛的龙珠雷达探测器的程序太垃圾了,所以找到我们这些ACM高手为龙珠雷达探测器写个程序,要求可以显示某颗龙珠所在的城市的位置,该龙珠所在的城市共有多少颗龙珠,龙珠移动过的次数。

布玛是个有钱人啊,写个程序我要价5百万,不算过分吧。因为本程序需要用到Union Find(并查集)算法,而且最困难的部分是如何压缩路径,不压缩路径自然容易做到,要压缩路径可以使得程序加快很多,故此要价5百万,O(∩_∩)O哈哈~。


路径压缩的思路是:

增加一个额外的移动记录次数,方便查找父母节点的时候更新孩子节点。


压缩路径之后程序块上100ms+;效果还是可以的。

不压缩路径的话,就直接接在一棵树上,计算移动次数的时候,直接计算到父母节点的距离就可以了。

Union Find的灵活运用,优化好的话,达到5星级难度的题目。


#include <stdio.h>

const int MAX_N = 10001;
struct Subset
{
	int xp, yNumBall, zTrans, addTrans;
};

Subset subs[MAX_N];
int N;

void initSubs()
{
	for (int i = 1; i <= N; i++)
	{
		subs[i].xp = 0;
		subs[i].yNumBall = 1;
		subs[i].zTrans = 0;
		subs[i].addTrans = 0;//the main help for path compression
	}
}

int findParent(int x)//with path compression
{
	if (subs[x].xp)	//do not use 0 index.
	{
		int p = subs[x].xp;
		subs[x].xp = findParent(p);	//update parent
		
		subs[x].zTrans += subs[p].addTrans;//careful:Update transportation times
		subs[x].addTrans += subs[p].addTrans;	//Watch out: +=, not =
		return subs[x].xp;
	}
	return x;
}

int findParent_2(int x)//without path compression
{
	int p = x;
	if (subs[x].xp)	//do not use 0 index.
	{
		p = findParent(subs[x].xp);	//update parent
		subs[x].zTrans = subs[subs[x].xp].zTrans+1;//Update transportation times
	}
	return p;
}

void unionTwo(int x, int y)
{
	int xp = findParent(x);
	int yp = findParent(y);
	if (xp == yp) return ;

	subs[xp].xp = yp;	//It should be yp, not y. add to its parent directly
	subs[yp].yNumBall += subs[xp].yNumBall;	//only record balls in parent
	subs[xp].addTrans++;	//transportation happen, add one more trans
	subs[xp].zTrans++;	//Watch out: update self's trans
}

int main()
{
	int T, Q, a, b;	//N cities and balls, Q quests
	char cmd;
	scanf("%d", &T);
	for (int t = 1; t <= T; t++)
	{
		scanf("%d %d", &N, &Q);
		initSubs();

		printf("Case %d:\n", t);
		while (Q--)
		{
			getchar();	// get rid of '\n'
			scanf("%c %d", &cmd, &a);
			if (cmd == 'T')
			{
				scanf("%d", &b);
				unionTwo(a, b);
			}
			else
			{
				int ap = findParent(a);
				printf("%d %d %d\n", ap, subs[ap].yNumBall, subs[a].zTrans);
			}//balls recorded in parent, trans times recorded in self node
		}
	}
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值