POJ 2195 解题报告

来源:互联网 发布:淘宝上的老兵户外军品 编辑:程序博客网 时间:2024/06/14 08:45

这道题是min-cost max-flow问题。写完后发现其实就是把find_path改成找一条cost最小的路径就可以(之前是用的bfs,找的是跳数最短的路径)。这种方法叫做 successive shortest path。应该是最简单的,还可以用之前maxflow的代码。Topcoder上面有非常好的讲解:https://www.topcoder.com/community/data-science/data-science-tutorials/minimum-cost-flow-part-two-algorithms/。

这道题最好的解法应该是KM algorithm(http://en.wikipedia.org/wiki/Hungarian_algorithm)。但是看起来不是很好懂的样子。

一如既往,我写的max-flow很慢:

thestoryofsnow2195Accepted716K672MSC++4168B

/* ID: thestor1 LANG: C++ TASK: poj2195 */#include <iostream>#include <fstream>#include <cmath>#include <cstdio>#include <cstring>#include <limits>#include <string>#include <vector>#include <list>#include <set>#include <map>#include <queue>#include <stack>#include <algorithm>#include <cassert>using namespace std;// there will be at most 100 housesconst int MAXPAIR = 100;const int INF = 1000;int find_path_cost(const int N, const int source, const int sink, const vector<vector<int> > &adjs, vector<vector<int> > &capacity, const vector<vector<int> > &cost){vector<int> dis(N, INF);dis[source] = 0;queue<int> que;que.push(source);std::vector<bool> isInQue(N, false);isInQue[source] = true;// the previous node in the shortest path from source to sinkstd::vector<int> from(N, -1);while (!que.empty()){int u = que.front();que.pop();for (int i = 0; i < adjs[u].size(); ++i){int v = adjs[u][i];if (capacity[u][v] > 0 && dis[u] + cost[u][v] < dis[v]){dis[v] = dis[u] + cost[u][v];from[v] = u;if (!isInQue[v]){que.push(v);}}}}// there is no path from source to sink in residual networkif (dis[sink] == INF){return -1;}// we compute the path capacityint prev, where = sink;int path_cap = -1;while (from[where] > -1){prev = from[where];assert (capacity[prev][where] > 0);if (path_cap < 0 || capacity[prev][where] < path_cap){path_cap = capacity[prev][where];}where = prev;}assert (path_cap > 0);// we update the residual network; if no path is found the while loop will not be enteredint pathcost = 0;where = sink;while (from[where] > -1){prev = from[where];capacity[prev][where] -= path_cap;capacity[where][prev] += path_cap;pathcost += path_cap * cost[prev][where];where = prev;}return pathcost;}int main(){int N, M;vector<pair<int, int> > houses(MAXPAIR), men(MAXPAIR);while (scanf("%d%d", &N, &M) && N && M){string line;int nmen = 0, nhouses = 0;for (int i = 0; i < N; ++i){cin >> line;assert (line.size() == M);for (int j = 0; j < M; ++j){if (line[j] == 'm'){men[nmen] = make_pair(i, j);nmen++;}else if (line[j] == 'H'){houses[nhouses] = make_pair(i, j);nhouses++;}}}assert (nmen == nhouses);// source, men, houses, sink// adjs[u] includes adjacent edges of uconst int TOTAL = 1 + nmen + nhouses + 1;vector<vector<int> > adjs(TOTAL, vector<int> ());vector<vector<int> > capacity(TOTAL, vector<int> (TOTAL, 0));vector<vector<int> > cost(TOTAL, vector<int> (TOTAL, 0));// source to men// seq: 0for (int i = 0; i < nmen; ++i){adjs[0].push_back(i + 1);adjs[i + 1].push_back(0);capacity[0][i + 1] = 1;cost[0][i + 1] = 0;cost[i + 1][0] = 0;}// men to houses// seq: 1 ~ nmenfor (int i = 0; i < nmen; ++i){for (int j = 0; j < nhouses; ++j){adjs[i + 1].push_back(nmen + 1 + j);adjs[nmen + 1 + j].push_back(i + 1);capacity[i + 1][nmen + 1 + j] = 1;cost[i + 1][nmen + 1 + j] = abs((double)(men[i].first - houses[j].first)) + abs((double)(men[i].second - houses[j].second));cost[nmen + 1 + j][i + 1] = -cost[i + 1][nmen + 1 + j];}}// houses to sink// seq: nmen + 1 ~ nmen + nhousesfor (int i = 0; i < nhouses; ++i){adjs[nmen + 1 + i].push_back(nmen + nhouses + 1);adjs[nmen + nhouses + 1].push_back(nmen + 1 + i);capacity[nmen + 1 + i][nmen + nhouses + 1] = 1;cost[nmen + 1 + i][nmen + nhouses + 1] = 0;cost[nmen + nhouses + 1][nmen + 1 + i] = 0;}int totalcost = 0;while (true){int pathcost = find_path_cost(TOTAL, 0, TOTAL - 1, adjs, capacity, cost);if (pathcost < 0){break;}else{totalcost += pathcost;}}printf("%d\n", totalcost);}return 0;}


0 0
原创粉丝点击