首页 > 代码库 > poj Going Home

poj Going Home

                               Going Home

 

题目:

   给出一个N*M的图,图上的m表示人,H表示房子,每座房子只能有一个人,要求你所有人到房子中总步数最少。m个数与H个数一样多。

 

算法分析:

   这个题目还是比较裸的。可以想到先求出每个人到每座房子的距离。然后求出最小花费,这个好像就是最小费用流吧?一开始用了KM写完后,发现。。。。哪里不对啊?后来才觉悟,原来题目是求解最小花费,KM是最大匹配下最大权值。。。。。

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <cstdio>
#include <cstring>
using namespace std;

typedef pair<int,int> P;
const int INF = 1 << 20;
const int MAXN = 400 + 10;

/////////////////////////////
//最小费用

struct Edge{
    int to,cap,cost,rev;
    Edge(){};
    Edge(int _to,int _cap,int _cost,int _rev)
        :to(_to),cap(_cap),cost(_cost),rev(_rev){};
};

vector<Edge> G[MAXN];
int V;
int h[MAXN];
int dist[MAXN];
int prevv[MAXN],preve[MAXN];

int src,sink;

///////////////////////////////////////

//查找距离
struct Point{
   int x,y,dis;
   Point(){};
   Point(int _x,int _y,int _dis)
        :x(_x),y(_y),dis(_dis){};
};
vector<Point> cost;
map<int,int> mp;
int N,M,cnt1,cnt2;
char str[MAXN][MAXN];
int dirx[5] = {-1,1,0,0};
int diry[5] = {0,0,-1,1};
int W[MAXN][MAXN],ans[MAXN];
int slack,Lx[MAXN],Ly[MAXN],Link[MAXN];
bool S[MAXN],T[MAXN];

////////////////////////////////////

bool check(int x,int y){
   if(x >= 0&& x < N&&y >=0 && y < M)
      return true;
   return false;
}
void bfs(int s,int e){
     bool vst[MAXN][MAXN];
     memset(vst,0,sizeof(vst));
     queue <Point> que;
     que.push(Point(s,e,0));
     vst[s][e] = 1;
     while(!que.empty()){
          Point pv = que.front(); que.pop();
          for(int i = 0;i < 4;++i){
             Point tmp;
             tmp.x = pv.x + dirx[i];
             tmp.y = pv.y + diry[i];
             tmp.dis = pv.dis + 1;
             if(check(tmp.x,tmp.y)&&!vst[tmp.x][tmp.y]){
                vst[tmp.x][tmp.y] = 1;
                if(str[tmp.x][tmp.y] == 'H'){
                    int num = tmp.x * N + tmp.y;
                    if(mp.count(num) == 0){
                        mp[num] = ++cnt2;
                    }
                    cost.push_back(Point(cnt1,mp[num],tmp.dis));
                }
                que.push(tmp);
             }
          }
     }
}
//
//bool Match(int i){
//    S[i] = true;
//    for(int j = 1;j <= cnt2;++j)if(!T[j]){
//        int tmp =   Lx[i] + Ly[j] - W[i][j];
//        if(tmp == 0){
//            T[j] = true;
//            if(Link[j] == -1||Match(Link[j])){
//                Link[j] = i;
//                return true;
//            }
//        }
//        else if(tmp < slack)
//            slack = tmp;
//    }
//    return false;
//}
//
//void update(int d){
//   for(int i = 1;i <= cnt1;++i)
//      if(S[i]) Lx[i] -= d;
//   for(int i = 1;i <= cnt2;++i)
//      if(T[i]) Ly[i] += d;
//}
//
//bool EK(){
//   for(int i = 1;i <= cnt1;++i){
//       Link[i] = -1;
//       Lx[i] = Ly[i] = 0;
//       for(int j = 1;j <= cnt2;++j)
//          Lx[i] = max(Lx[i],W[i][j]);
//   }
//
//   slack = INF;
//
//   for(int i = 1;i <= cnt1;++i){
//      for(;;){
//        memset(S,false,sizeof(S));
//        memset(T,false,sizeof(T));
//        if(Match(i))
//            break;
//
//        if(slack == INF)
//            return false;
//        update(slack);
//      }
//
//   }
//   return true;
//}
//
//int getAns(){
//   int sum = 0;
//   for(int j = 1;j <= cnt2;++j){
//       if(Link[j] != -1)
//         sum += W[Link[j]][j];
//   }
//   return sum;
//}

void addEdge(int from,int to,int cap,int cost){
    G[from].push_back(Edge(to,cap,cost,G[to].size()));
    G[to].push_back(Edge(from,0,-cost,G[from].size() - 1));
}


int min_cost_flow(int s,int t,int f){
   int res = 0;
   V = sink + 1;
   fill(h,h + V,0);
   while(f > 0){
       priority_queue<P,vector<P>,greater<P> > que;
       fill(dist,dist + V,INF);
       dist[s] = 0;
       que.push(P(0,s));
       while(!que.empty()){
           P p = que.top(); que.pop();
           int v = p.second;
           if(dist[v] < p.first) continue;
           for(int i = 0;i < (int)G[v].size();++i){
               Edge& e = G[v][i];
               int tmp = dist[v] + e.cost + h[v] - h[e.to];
               if(e.cap > 0 && dist[e.to] > tmp){
                    dist[e.to] = tmp;
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.push(P(dist[e.to],e.to));
               }
           }
       }

       if(dist[t] == INF){
           return -1;
       }

       for(int v = 1;v < V;++v) h[v] += dist[v];

       int dd = f;
       for(int v = t;v != s ;v = prevv[v]){
          dd = min(dd,G[prevv[v]][preve[v]].cap);
       }

       f -= dd;
       res += dd * h[t];
       for(int v = t;v != s;v = prevv[v]){
          Edge& e = G[prevv[v]][preve[v]];
          e.cap -= dd;
          G[v][e.rev].cap += dd;
       }
   }
   return res;
}

void init(){
    for(int i = 0;i <= sink;++i)
        G[i].clear();
}

void solve(){
   cnt1 = 0;
   cnt2 = 0;
   mp.clear();
   cost.clear();
   //查找距离
   for(int i = 0;i < N;++i){
     for(int j = 0;j < M;++j){
         if(str[i][j] == 'm'){
            cnt1++;
            bfs(i,j);
         }
     }
   }

   Point tmp;
   for(int i = 0;i < (int)cost.size();++i){
       tmp = cost[i];
       W[tmp.x][tmp.y] = tmp.dis;
   }

   //建图
   V = cnt1 + cnt2;
   src = http://www.mamicode.com/V + 1; sink = src + 1;>


 

poj Going Home