zju 2334 monkey king

    因为最近在学习二项堆,所以拿这题练练手。其实这题思路很清晰,就是在二项堆中加入并查集的特性。因为在一个sb的地方犯了一个sb的错误,卡了几个小时。一切尽在代码中……

/*
 * zoj2334 monkey king
 */
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define CNT 100010
const int INTMAX = (int)1e8;

struct BinomialNode {

	//Binomial data
	int sibling;
	int child;
	int disjointp; //use it for Binomial Head too
	int degree;

	//monkey data
	int monkey;
	int strongness;
};
BinomialNode node[CNT];
int monkeyNode[CNT];

int N, M;

int FindDisjointP( int a )
{
	if ( node[a].disjointp > 0 ) {
		node[a].disjointp = FindDisjointP( node[a].disjointp );
		return node[a].disjointp;
	}
	return a;
}

int FindMax( int a )
{
	int max = -INTMAX, k=-1;
	while ( a > 0 )
	{
		if ( node[a].strongness > max )
		{
			max = node[a].strongness;
			k = a;
		}
		a = node[a].sibling;
	}
	return k;
}

inline void swap( int& a, int& b )
{
	a = a^b;
	b = a^b;
	a = a^b;
}

void Adjust( int a )
{
	int max = -INTMAX;
	int lchild, k=-1;
	
	lchild = node[a].child;
	while ( lchild > 0 )
	{
		if ( node[lchild].strongness > max )
		{
			max = node[lchild].strongness;
			k = lchild;
		}
		lchild = node[lchild].sibling;
	}
	if ( k > 0 && max > node[a].strongness ) {  // too sb here, without 'max > node[a].strongness'
		
		swap( node[a].strongness, node[k].strongness );
		swap( node[a].monkey, node[k].monkey );
		monkeyNode[ node[a].monkey ] = a;
		monkeyNode[ node[k].monkey ] = k;

		Adjust( k );
	}
}

inline void Link( int a, int pb, int& head )
{
	++ node[pb].degree;
	node[a].sibling = node[pb].child;
	node[pb].child = a;
	if ( a == head )
	{
		node[a].disjointp = pb;
		node[pb].disjointp = -1;

		//and pb become a new head!
		head = pb;
	}
}

int Merge( int a, int b )
{
	int ptra=a, ptrb=b, ptr=0, head=-1;

	while ( ptra > 0 && ptrb > 0 )
	{
		if ( node[ptra].degree < node[ptrb].degree )
		{
			node[ptr].sibling = ptra;
			if ( -1 == head )
			{
				head = ptra;
				node[ptrb].disjointp = head;
			}
			ptra = node[ptra].sibling;
		}
		else {
			node[ptr].sibling = ptrb;
			if ( -1 == head )
			{
				head = ptrb;
				node[ptra].disjointp = head;
			}
			ptrb = node[ptrb].sibling;
		}
		ptr = node[ptr].sibling;
	} 	
	node[head].disjointp = -1;
	node[ptr].sibling = ptra > 0 ? ptra : ptrb;

	return head;
}

void Union( int a, int b )
{
	//merge head list
	int ptra=a, ptrb=b, ptr=0, head;
	head = Merge( a, b );
	
	//then link nodes whose have the same nodes count.
	ptra = -1;
	ptrb = node[head].sibling;
	ptr = head;
	while ( ptrb > 0 )
	{
		if ( node[ptr].degree != node[ptrb].degree ||
			( node[ptrb].sibling > 0 && node[ptrb].degree == node[ node[ptrb].sibling ].degree ) )
		{
			ptra = ptr;
			ptr = ptrb;
		}
		else if ( node[ptr].strongness <= node[ptrb].strongness )
		{
			if ( ptra > 0 )
				node[ptra].sibling = ptrb;
			//link 
			Link( ptr, ptrb, head );
			ptr = ptrb;
		}
		else  {
			node[ptr].sibling = node[ptrb].sibling;
			//link
			Link( ptrb, ptr, head );
		}
		ptrb = node[ptr].sibling;
	}
}

int main()
{
	int i, a, b, pa, pb, ma, mb;
	while ( scanf("%d", &N) != EOF )
	{
		memset( node, 0, sizeof(BinomialNode)*(N+1) );

		for ( i = 1; i <= N; ++ i )
		{
			scanf("%d", &node[i].strongness);
			node[i].monkey = i;
			monkeyNode[i] = i;
		}
		
		scanf("%d", &M);
		for ( i = 1; i <= M; ++ i )
		{
			scanf("%d%d", &a, &b );
			pa = FindDisjointP( monkeyNode[a] );  //find Binomial head
			pb = FindDisjointP( monkeyNode[b] );
			if ( pa == pb )
				printf("-1\n");
			else
			{
				ma = FindMax(pa);     //find Binomial tree max node
				node[ma].strongness /= 2;
				Adjust( ma );

				mb = FindMax(pb);
				node[mb].strongness /= 2;
				Adjust( mb );

				Union( pa, pb );	

				pa = FindDisjointP( pa );
				ma = FindMax(pa);
				printf( "%d\n", node[ma].strongness );
			}
		}	
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值