/** Find an edge group coloring in a bipartite group graph. * The algorithm used here is a variant of the menu graph method. * It maintains a separate menu graph for each output, and a maximum * matching for each. It also maintains a "deficit" for each edge group, * which is the number of menu graphs for which the group is unmatched. * It then repeatedly selects the group with the largest deficit and * adjusts its menu to reduce its deficit. * Once all deficits are zero, it colors the edges based on the matchings * in the menu graphs. * @param g is a reference to the graph * @param edgeColors is an array indexed by edge numbers which is allocated * by the caller; on return edgeColors[e] is the color assigned to edge e * @return the number of colors used */ egGmenu::egGmenu(GroupGraph& g, int edgeColors[]) : egMenu(g, edgeColors) { // create heap sorted by negative group size Dheap<int> groups(gp->M()); for (int grp = 1; grp <= gp->M(); grp++) { if (gp->groupSize(grp) > 0) groups.insert(grp,-(gp->groupSize(grp))); } // repeatedly select next largest group and expand menu until it // is matched in all its menu graphs maxColor = max(g.maxGroupCountIn(), g.maxDegreeOut()); while (!groups.empty()) { int grp = groups.deletemin(); vertex u = gp->input(gp->firstEdgeInGroup(grp)); int k = (maxColor + (gp->groupCount(u)-1))/gp->groupCount(u); while (true) { // select available color with the largest gain for grp int best = 0; int bestGain = 0; for (int c = avail[u].first(); c != 0 && c <= maxColor; c = avail[u].next(c)) { int cgain = gain(c,grp); if (cgain > bestGain) { best = c; bestGain = cgain; } } if (bestGain <= 0 || menuSize(grp) >= k) { maxColor++; best = maxColor; resetMenu(grp); k = (maxColor + (gp->groupCount(u)-1))/ gp->groupCount(u); } if (growMenu(grp, best) == 0) break; } } for (vertex v = gp->firstOut(); v != 0; v = gp->nextOut(v)) { Graph& mg = *mgraf[v]; dynamicMatch& dm = *dymatch[v]; // now color the edges using the matching for (edge e = gp->firstAt(v); e != 0; e = gp->nextAt(v,e)) { color[e] = mg.right(dm.matchEdge(gx[e]))-gp->degree(v); } } }
u32 cPopMenu::itemBelowPoint( const cPoint & pt ) { cPoint menuPos(position().x + _barLeft, position().y + _itemTopLeftPoint.y - 2); cSize menuSize(barWidth(), _itemHeight * _items.size()); cRect rect(menuPos, menuPos + menuSize); if( rect.surrounds( pt ) ) { u32 item = (pt.y - menuPos.y ) / _itemHeight; if( item > _items.size() - 1) item = _items.size() - 1; return item; } return (u32)-1; }