public Biclique findMaximumBiclique() {
        if (0 == this.tc.getE()) {
            return null;
        }

        Biclique biclique = new Biclique();

        // store next search space
        boolean[] search_L = new boolean[this.tc.getV()];
        boolean[] search_R = new boolean[this.tc.getV()];

        // init search space to true, aka. available
        for (int i = 0; i < this.tc.getV(); i++) {
            search_L[i] = !this.L_DegreeIndicators[i].zero();
            search_R[i] = !this.R_DegreeIndicators[i].zero();
        }
        
        /**
        // find the rest
        DegreeIndicator di = findMaxOfBoth(this.L_DegreeIndicators,
                search_L, this.R_DegreeIndicators, search_R, Partite.L);
        while (di != null) {
            if (Partite.L == di.getPartite()) {
                int index = di.getIndex();
                
                biclique.L.add(index);
                search_L[index] = false;
                update_search_R(search_R, index);
            } else if (Partite.R == di.getPartite()) {
                int index = di.getIndex();
                
                biclique.R.add(index);
                search_R[index] = false;
                update_search_L(search_L, index);
            }

            di = findMaxOfBoth(this.L_DegreeIndicators, search_L,
                    this.R_DegreeIndicators, search_R, di.getPartite());
        }

        */
       
        
        // find first
        DegreeIndicator di_fir = findMaxOfBoth(this.L_DegreeIndicators,
                search_L, this.R_DegreeIndicators, search_R, Partite.L);
        if (null == di_fir) {
            throw new RuntimeException("no di in both partites");
        }

        // cover first and find second
        if (Partite.L == di_fir.getPartite()) {
            int index = di_fir.getIndex();
            
            biclique.L.add(index);
            search_L[index] = false;
            update_search_R(search_R, index);
            
            // find second
            index = findMax(this.R_DegreeIndicators, search_R);
            
            biclique.R.add(index);
            search_R[index] = false;
            update_search_L(search_L, index);
        } else if (Partite.R == di_fir.getPartite()) {
            int index = di_fir.getIndex();
            
            biclique.R.add(index);
            search_R[index] = false;
            update_search_L(search_L, index);

            index = findMax(this.L_DegreeIndicators, search_L);

            biclique.L.add(index);
            search_L[index] = false;
            update_search_R(search_R, index);
        }

        // find the rest
        DegreeIndicator di = findMaxOfBoth(this.L_DegreeIndicators,
                search_L, this.R_DegreeIndicators, search_R, Partite.L);
        while (di != null) {
            if (Partite.L == di.getPartite()) {
                int index = di.getIndex();
                
                biclique.L.add(index);
                search_L[index] = false;
                update_search_R(search_R, index);
            } else if (Partite.R == di.getPartite()) {
                int index = di.getIndex();
                
                biclique.R.add(index);
                search_R[index] = false;
                update_search_L(search_L, index);
            }

            di = findMaxOfBoth(this.L_DegreeIndicators, search_L,
                    this.R_DegreeIndicators, search_R, di.getPartite());
        }
        

        return biclique;
    }