JMK no matter what

Hungarian Method

옛날에 했던 구현.

lang:cpp
struct Hungarian
{ 
  int n, result;
  vector<vector<int> > adj;
  vector<int> rowMatch, colMatch;
  vector<bool> seen, rowSelected, colSelected;
  vector<vector<int> > weight;

  operator int () { return result; }

  Hungarian(const vector<vector<int> >& w)
    : n(w.sz), adj(w.sz), rowMatch(w.sz), colMatch(w.sz), seen(w.sz), rowSelected(w.sz), colSelected(w.sz), weight(w)
  {
    REP(i,n) { int min = *min_element(all(weight[i])); REP(j,n) weight[i][j] -= min; }
    REP(i,n) { int min = weight[0][i]; FOR(j,1,n) min <?= weight[j][i]; REP(j,n) weight[j][i] -= min; }

    while (true)
    {   
      REP(i,n) adj[i].clear();
      REP(i,n) REP(j,n) if (weight[i][j] == 0) adj[i].push_back(j);
      if (match() == n) break;
      selectLine();
      int min = 987654321;
      REP(i,n) if(!rowSelected[i]) REP(j,n) if(!colSelected[j]) min <?= weight[i][j];
      REP(i,n) REP(j,n)
      {
        if (rowSelected[i] && colSelected[j]) weight[i][j] += min;
        if (!rowSelected[i] && !colSelected[j]) weight[i][j] -= min;
      }
    }
    result = 0;
    REP(i,n) result += w[i][rowMatch[i]];
  }

  bool augment(int here)
  {
    REP(i,adj[here].sz)
    {
      int there = adj[here][i];
      if (seen[there]) continue; seen[there] = true;
      if (colMatch[there] == -1 || augment(colMatch[there])) { rowMatch[here] = there; colMatch[there] = here; return true; }
    }
    return false;
  }

  int match()
  {
    fill(all(rowMatch), -1); fill(all(colMatch), -1);
    int ret = 0; REP(i,n) { fill(all(seen) ,0); if (augment(i)) ret++; }
    return ret;
  }

  void selectLine()
  {
    vector<int> rq, cq;
    REP(i,n) colSelected[i] = rowSelected[i] = false;
    REP(i,n) if (rowMatch[i] != -1) rowSelected[i] = true; else rq.pb(i);

    while (!rq.empty())
    {
      cq.clear();
      REP(i,rq.sz)
      {
        int here = rq[i];
        REP(there,n)
        {
          if (colSelected[there]) continue;
          if (!weight[here][there] && rowMatch[here] != there)
          {
            colSelected[there] = true;
            cq.push_back(there);
          }
        }
      }
      rq.clear();
      REP(i,cq.sz)
      {
        int here = cq[i];
        if (!rowSelected[colMatch[here]]) continue;
        rowSelected[colMatch[here]] = 0;
        rq.push_back(colMatch[here]);
      }
    }
  }
};
2010-06-10 14:11:46 | JM | /logs/library/ | 2 Comments
wook
2010-06-10 21:40:42
아...아름다운 코드에요
JM
2010-06-11 00:00:30
@wook, 별로 안 아름다운거 알아 이러지말어 ㅋㅋㅋ

Leave a comment

春來不似春

About

Eventstream

Pages

Guestbook

Search

Site Admin

Recent Comments