POJ 2195 最小费用流

题目链接

 第一次做最小费用流的问题,之前一直是盲点。

从这道题来看,我对最小费用最大流的理解是,在最大流约束的条件下,每次寻找可行路都找费用最小的那一条,做若干次最短路,直到最后没有增广路。

这道题点的总数可达到202,第一次交题的时候没注意,导致RE


#include
#include
#include
#include
#include
#include
#include
#include
#define lson node<<1,l,l+r>>1
#define rson node<<1|1,(l+r>>1)+1,r
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int _maxNodes = 1e5+10;

struct Node{
    int x, y;
    Node(){}
    Node(int u, int v){
        x = u; y = v;
    }
};

Node man[210], house[210];
int n,m;
char graph[210][210];
int num_m, num_h;
int source, sink;
int cost[210][210], d[210][210];
int parent[210];
bool vis[210];
int mincost[210];
int ans;


void init(){
    for (int i = 0; i < n; i++){
        scanf("%s", graph[i]);
    }

    num_m = num_h = 0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            if (graph[i][j] == 'H'){
                house[++num_h] = Node(i, j);
            }
            else if (graph[i][j] == 'm'){
                man[++num_m] = Node(i, j);
            }
        }
    }
    source =  0; sink = num_m + num_h + 1;

    memset(cost,0,sizeof cost);
    memset(d,0,sizeof d);
    for (int i = 1; i <= num_m; i++){
        d[source][i] = 1;
    }
    for (int i = 1; i <= num_m; i++){
        for (int j = 1; j <= num_h; j++){
            d[i][num_m+j] = 1;
            cost[i][num_m+j] = abs(man[i].x - house[j].x) + abs(man[i].y - house[j].y);
            cost[num_m+j][i] = -cost[i][num_m+j];
        }
    }
    for (int i = 1; i <= num_h; i++){
        d[num_m+i][sink] = 1;
    }
}


void SPFA(){
    queue que;
    int v, i;
    memset(vis,false,sizeof(vis));
    memset(parent,-1,sizeof (parent));
    for (i = source; i <= sink; i++) mincost[i] = INF;

    que.push(source);
    mincost[source] = 0;
    vis[source] = true;

    while (!que.empty()){
        v = que.front(); que.pop();
        vis[v] = false;

        for (i = source; i <= sink; i++){
            if (d[v][i] && mincost[v] + cost[v][i] < mincost[i]){
                mincost[i] = mincost[v] + cost[v][i];
                parent[i] = v;
                if (!vis[i]){
                    que.push(i);
                    vis[i] = true;
                }
            }
        }
    }

}

void solve(){
    int v;
    ans = 0;
    while (1){
        SPFA();
        if (parent[sink] == -1) break;

        v = sink;
        while (parent[v] != -1){
            d[parent[v]][v] -= 1;
            d[v][parent[v]] += 1;
            v = parent[v];
        }
        ans += mincost[sink];
    }
    printf("%d\n",ans);
}

int main(){
    while (scanf("%d %d",&n, &m) == 2){
        if (n == 0 && m == 0) break;
        init();
        solve();
    }
    return 0;
}


你可能感兴趣的:(POJ 2195 最小费用流)