因为最近在学习二项堆,所以拿这题练练手。其实这题思路很清晰,就是在二项堆中加入并查集的特性。因为在一个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;
}