             if (src.id() >= dst.id()) return; // imposes ordering
             degree_t src_len = src.degree();
             degree_t dst_len = dst.degree();
-            int i = MAX_ADJ_UNIONS_BINS-1;
-            /*
-            if (i > 3)
-                i = 3;
-            */
+
+            degree_t u_len = (src_len <= dst_len) ? src_len : dst_len;
+            degree_t v_len = (src_len > dst_len) ? dst_len : src_len;
+            unsigned int log_v = 32-__clz(v_len-1);
+            int intersect_work = u_len + v_len - 1;
+            int binary_work = u_len * log_v;
+            int METHOD = (5*intersect_work >= binary_work);
+            total_work = METHOD ? u_len : u_len+v_len-1;
+            int cutoff = METHOD ? 3 : 31;
+            int i = MAX_ADJ_UNIONS_BINS/2;
             
-            total_work = src_len + dst_len - 1;
             int W;
             while (i > 0) {
                 W = d_queue_info.ptr()->queue_threads_per[i];

                    break;
                i-=1;
            }
            /*
            degree_t u_len = (src_len <= dst_len) ? src_len : dst_len;
            //degree_t v_len = (src_len > dst_len) ? dst_len : src_len;
            //unsigned int log_u = 32-__clz(u_len-1);
            //unsigned int log_v = 32-__clz(v_len-1);
            int W;
            while (i > 0) {
                W = d_queue_info.ptr()->queue_threads_per[i];
                if ((u_len+W-1)/W >= 3)
                    break;
                i-=1;
            }*/

            //int imbalanced_work_est = ((u_len+W-1)/W)*log_v;
            //int balanced_work_est = ((total_work+W-1)/W) + log_u;
            //bin_index = (K*balanced_work_est > imbalanced_work_est);
            bin_index = i;
            //bin_index=2;
            // Either count or add the item to the appropriate queue
            if (countOnly)
                atomicAdd(&(d_queue_info.ptr()->queue_sizes[bin_index]), 1ULL);

    // Phase 2: run the operator on each queued edge as appropriate
    for (auto bin = 0; bin < MAX_ADJ_UNIONS_BINS; bin++) {
        if (hd_queue_info().queue_sizes[bin] == 0) continue;
        int threads_per = hd_queue_info().queue_threads_per[bin % (MAX_ADJ_UNIONS_BINS/2)]; 
        TM.start();
        if (bin < MAX_ADJ_UNIONS_BINS/2) { 
            forAllEdgesAdjUnionBalanced(hornet, hd_queue_info().d_queues[bin], hd_queue_info().queue_pos[bin], op, threads_per, 0);
        } else if (bin >= MAX_ADJ_UNIONS_BINS/2) {
            forAllEdgesAdjUnionImbalanced(hornet, hd_queue_info().d_queues[bin], hd_queue_info().queue_pos[bin], op, threads_per, 1);
        }
        
        TM.stop();
        TM.print("queue processing:");
        TM.reset();
