因為最近在學習二項堆,所以拿這題練練手。其實這題思路很清晰,就是在二項堆中加入並查集的特性。因為在一個sb的地方犯了一個sb的錯誤,卡了幾個小時。一切盡在代碼中……
/* * zoj2334 monkey king */#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define CNT 100010const int INTMAX = (int)1e8;struct BinomialNode {//Binomial dataint sibling;int child;int disjointp; //use it for Binomial Head tooint degree;//monkey dataint 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 listint 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;//linkLink( 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 headpb = FindDisjointP( monkeyNode[b] );if ( pa == pb )printf("-1\n");else{ma = FindMax(pa); //find Binomial tree max nodenode[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;}