【最小费用最大流】POJ 2195

可以KM,也可以费用流,最近学费用流,所以用一下,debug真浪费时间,以为spfa有问题,原来是计数时出错。。。囧啊,菜啊,话说poj 2516到现在还不知道wa哪里,抓狂啊!!!

#define inf 1<<30
#define N 222
int cap[N][N];
int cost[N][N];
int pre[N];
int dis[N];
bool vis[N];
int minc;
char str[110][110];
int min(int a,int b){return a>b?b:a;}
void spfa(int s,int t){
    queue<int> qq;
    int i,j;
    while(1){
        for(i=s;i<=t;i++){
            vis[i] = 0;
            dis[i] = inf;
        }
        dis[s] = 0;
        qq.push(s);
        vis[s] = 1;
        while(!qq.empty()){
            int u = qq.front();
            qq.pop();
            vis[u] = 0;
            for(int v=s;v<=t;v++){
                if(cap[u][v] && dis[u] + cost[u][v] < dis[v]){
                    dis[v] = dis[u] + cost[u][v];
                    pre[v] = u;
                    if(!vis[v]){
                        vis[v] = 1;
                        qq.push(v);
                    }
                }
            }
        }
        if(dis[t] == inf){
            return ;
        }
        int a = inf;
        for(int u=t;u!=s;u=pre[u]){
            a = min(a,cap[pre[u]][u]);
        }
        for(int u=t;u!=s;u=pre[u]){
            cap[pre[u]][u] -= a;
            cap[u][pre[u]] += a;
        }
        minc += dis[t]*a;
    }
    return ;
}
struct node{
    int r,c;
}mm[N/2],hh[N/2];
int cntm ;
int cnth ;
void work(){
    int i,j;
    int s = 0,t = cntm + cnth + 1;
    minc =0;
    memset(cap,0,sizeof(cap));
    memset(cost,0,sizeof(cost));
    for(i=1;i<=cntm;i++){
        cap[s][i] = 1;//每条边容量为1,最后肯定是满流的
        cost[s][i] = 0;
    }
    for(i=1;i<=cnth;i++){
        cap[i+cntm][t] = 1;
        cost[i+cntm][t] = 0;
    }
    for(i=1;i<=cntm;i++){
        for(j=1;j<=cnth;j++){
            cap[i][j+cntm] = 1;
            cost[i][j+cntm] = abs(mm[i].r - hh[j].r) + abs(mm[i].c - hh[j].c);
            cost[j+cntm][i] = -cost[i][j+cntm];//注意要取反
        }
    }
    spfa(s,t);
    printf("%d\n",minc);
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m) && (n+m)){
        int i,j;
        for(i=1;i<=n;i++){
            scanf("%s",str[i]+1);
        }
        cntm = 0;
        cnth = 0;
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                if(str[i][j] == 'm'){
                    mm[++cntm].r = i;
                    mm[cntm].c = j;
                } else if(str[i][j] == 'H'){
                    hh[++cnth].r = i;
                    hh[cnth].c = j;
                }
            }
        }cout<<cntm<<endl;
        work();
    }
    return 0;
}


















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