Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/mincover.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* mincover.c4*5* This file implements the minimum cover algorithm6*7* Started 8/1/978* George9*10* $Id: mincover.c 9942 2011-05-17 22:09:52Z karypis $11*/1213#include "metislib.h"1415/*************************************************************************16* Constants used by mincover algorithm17**************************************************************************/18#define INCOL 1019#define INROW 2020#define VC 121#define SC 222#define HC 323#define VR 424#define SR 525#define HR 6262728/*************************************************************************29* This function returns the min-cover of a bipartite graph.30* The algorithm used is due to Hopcroft and Karp as modified by Duff etal31* adj: the adjacency list of the bipartite graph32* asize: the number of vertices in the first part of the bipartite graph33* bsize-asize: the number of vertices in the second part34* 0..(asize-1) > A vertices35* asize..bsize > B vertices36*37* Returns:38* cover : the actual cover (array)39* csize : the size of the cover40**************************************************************************/41void MinCover(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *cover, idx_t *csize)42{43idx_t i, j;44idx_t *mate, *queue, *flag, *level, *lst;45idx_t fptr, rptr, lstptr;46idx_t row, maxlevel, col;4748mate = ismalloc(bsize, -1, "MinCover: mate");49flag = imalloc(bsize, "MinCover: flag");50level = imalloc(bsize, "MinCover: level");51queue = imalloc(bsize, "MinCover: queue");52lst = imalloc(bsize, "MinCover: lst");5354/* Get a cheap matching */55for (i=0; i<asize; i++) {56for (j=xadj[i]; j<xadj[i+1]; j++) {57if (mate[adjncy[j]] == -1) {58mate[i] = adjncy[j];59mate[adjncy[j]] = i;60break;61}62}63}6465/* Get into the main loop */66while (1) {67/* Initialization */68fptr = rptr = 0; /* Empty Queue */69lstptr = 0; /* Empty List */70for (i=0; i<bsize; i++) {71level[i] = -1;72flag[i] = 0;73}74maxlevel = bsize;7576/* Insert free nodes into the queue */77for (i=0; i<asize; i++)78if (mate[i] == -1) {79queue[rptr++] = i;80level[i] = 0;81}8283/* Perform the BFS */84while (fptr != rptr) {85row = queue[fptr++];86if (level[row] < maxlevel) {87flag[row] = 1;88for (j=xadj[row]; j<xadj[row+1]; j++) {89col = adjncy[j];90if (!flag[col]) { /* If this column has not been accessed yet */91flag[col] = 1;92if (mate[col] == -1) { /* Free column node was found */93maxlevel = level[row];94lst[lstptr++] = col;95}96else { /* This column node is matched */97if (flag[mate[col]])98printf("\nSomething wrong, flag[%"PRIDX"] is 1",mate[col]);99queue[rptr++] = mate[col];100level[mate[col]] = level[row] + 1;101}102}103}104}105}106107if (lstptr == 0)108break; /* No free columns can be reached */109110/* Perform restricted DFS from the free column nodes */111for (i=0; i<lstptr; i++)112MinCover_Augment(xadj, adjncy, lst[i], mate, flag, level, maxlevel);113}114115MinCover_Decompose(xadj, adjncy, asize, bsize, mate, cover, csize);116117gk_free((void **)&mate, &flag, &level, &queue, &lst, LTERM);118119}120121122/*************************************************************************123* This function perfoms a restricted DFS and augments matchings124**************************************************************************/125idx_t MinCover_Augment(idx_t *xadj, idx_t *adjncy, idx_t col, idx_t *mate, idx_t *flag, idx_t *level, idx_t maxlevel)126{127idx_t i;128idx_t row = -1;129idx_t status;130131flag[col] = 2;132for (i=xadj[col]; i<xadj[col+1]; i++) {133row = adjncy[i];134135if (flag[row] == 1) { /* First time through this row node */136if (level[row] == maxlevel) { /* (col, row) is an edge of the G^T */137flag[row] = 2; /* Mark this node as being visited */138if (maxlevel != 0)139status = MinCover_Augment(xadj, adjncy, mate[row], mate, flag, level, maxlevel-1);140else141status = 1;142143if (status) {144mate[col] = row;145mate[row] = col;146return 1;147}148}149}150}151152return 0;153}154155156157/*************************************************************************158* This function performs a coarse decomposition and determines the159* min-cover.160* REF: Pothen ACMTrans. on Amth Software161**************************************************************************/162void MinCover_Decompose(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *mate, idx_t *cover, idx_t *csize)163{164idx_t i, k;165idx_t *where;166idx_t card[10];167168where = imalloc(bsize, "MinCover_Decompose: where");169for (i=0; i<10; i++)170card[i] = 0;171172for (i=0; i<asize; i++)173where[i] = SC;174for (; i<bsize; i++)175where[i] = SR;176177for (i=0; i<asize; i++)178if (mate[i] == -1)179MinCover_ColDFS(xadj, adjncy, i, mate, where, INCOL);180for (; i<bsize; i++)181if (mate[i] == -1)182MinCover_RowDFS(xadj, adjncy, i, mate, where, INROW);183184for (i=0; i<bsize; i++)185card[where[i]]++;186187k = 0;188if (iabs(card[VC]+card[SC]-card[HR]) < iabs(card[VC]-card[SR]-card[HR])) { /* S = VC+SC+HR */189/* printf("%"PRIDX" %"PRIDX" ",vc+sc, hr); */190for (i=0; i<bsize; i++)191if (where[i] == VC || where[i] == SC || where[i] == HR)192cover[k++] = i;193}194else { /* S = VC+SR+HR */195/* printf("%"PRIDX" %"PRIDX" ",vc, hr+sr); */196for (i=0; i<bsize; i++)197if (where[i] == VC || where[i] == SR || where[i] == HR)198cover[k++] = i;199}200201*csize = k;202gk_free((void **)&where, LTERM);203204}205206207/*************************************************************************208* This function perfoms a dfs starting from an unmatched col node209* forming alternate paths210**************************************************************************/211void MinCover_ColDFS(idx_t *xadj, idx_t *adjncy, idx_t root, idx_t *mate, idx_t *where, idx_t flag)212{213idx_t i;214215if (flag == INCOL) {216if (where[root] == HC)217return;218where[root] = HC;219for (i=xadj[root]; i<xadj[root+1]; i++)220MinCover_ColDFS(xadj, adjncy, adjncy[i], mate, where, INROW);221}222else {223if (where[root] == HR)224return;225where[root] = HR;226if (mate[root] != -1)227MinCover_ColDFS(xadj, adjncy, mate[root], mate, where, INCOL);228}229230}231232/*************************************************************************233* This function perfoms a dfs starting from an unmatched col node234* forming alternate paths235**************************************************************************/236void MinCover_RowDFS(idx_t *xadj, idx_t *adjncy, idx_t root, idx_t *mate, idx_t *where, idx_t flag)237{238idx_t i;239240if (flag == INROW) {241if (where[root] == VR)242return;243where[root] = VR;244for (i=xadj[root]; i<xadj[root+1]; i++)245MinCover_RowDFS(xadj, adjncy, adjncy[i], mate, where, INCOL);246}247else {248if (where[root] == VC)249return;250where[root] = VC;251if (mate[root] != -1)252MinCover_RowDFS(xadj, adjncy, mate[root], mate, where, INROW);253}254255}256257258259260261