hdu1533 最小费用最大流

题意

题意很简单,给一张100*100以内的图,H和m个数相同,进行匹配,求路径最小的一个方案

思路

建立两个源点,s和t。然后将H和m的位置离散化,s连接H,t连接s,H和m连接流量1,费用为两个坐标的曼哈顿距离。bellmanford一套就ok

bellmanford模板

struct node{
    int next,to,flow,cost,c;
}edge[M];
int head[N],tot,s,t;
int maxflow,mincost;//最大流 最小费用
void inint(){mem(head,-1);tot=0;}
void add(int u,int v,int c,int cost){
    edge[tot].next=head[u];edge[tot].to=v;edge[tot].c=c;edge[tot].flow=0;edge[tot].cost=cost;head[u]=tot++;
    edge[tot].next=head[v];edge[tot].to=u;edge[tot].c=0;edge[tot].flow=0;edge[tot].cost=-cost;head[v]=tot++;
}
int dis[N],vis[N],pv[N],pe[N],a[N];
bool bellmanford(int s,int t){
    for(int i=0;i<N;i++){dis[i]=inf;vis[i]=0;pv[i]=-1;}
    dis[s]=0;pv[s]=-1;a[s]=inf;
    queue<int>q;
    q.push(s);
    vis[s]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to,cap=edge[i].c,flow=edge[i].flow,cost=edge[i].cost;
            if(cap>flow && dis[v]>dis[u]+cost){
                dis[v]=dis[u]+cost;
                pv[v]=u;
                pe[v]=i;
                a[v]=min(a[u],cap-flow);
                if(!vis[v]){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    if(dis[t]==inf){
        return false;
    }
    maxflow+=a[t];
    mincost+=dis[t]*a[t];
    for(int i=t;i!=s;i=pv[i]){
        edge[pe[i]].flow+=a[t];
        edge[pe[i]^1].flow-=a[t];
    }
    return true;
}
void kkkk(){
    while(bellmanford(s,t)){continue;}
    return;
}

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
const double pi=acos(-1.0);
const int N=1e4+10,M=2e5+10;
int n,m;
char mp[110][110];
int H[10010],man[10010],Hnum,mannum;
struct node{
    int next,to,flow,cost,c;
}edge[M];
int head[N],tot,s,t;
int maxflow,mincost;//最大流 最小费用
void inint(){mem(head,-1);tot=0;}
void add(int u,int v,int c,int cost){
    edge[tot].next=head[u];edge[tot].to=v;edge[tot].c=c;edge[tot].flow=0;edge[tot].cost=cost;head[u]=tot++;
    edge[tot].next=head[v];edge[tot].to=u;edge[tot].c=0;edge[tot].flow=0;edge[tot].cost=-cost;head[v]=tot++;
}
int dis[N],vis[N],pv[N],pe[N],a[N];
bool bellmanford(int s,int t){
    for(int i=0;i<N;i++){dis[i]=inf;vis[i]=0;pv[i]=-1;}
    dis[s]=0;pv[s]=-1;a[s]=inf;
    queue<int>q;
    q.push(s);
    vis[s]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to,cap=edge[i].c,flow=edge[i].flow,cost=edge[i].cost;
            if(cap>flow && dis[v]>dis[u]+cost){
                dis[v]=dis[u]+cost;
                pv[v]=u;
                pe[v]=i;
                a[v]=min(a[u],cap-flow);
                if(!vis[v]){
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    if(dis[t]==inf){
        return false;
    }
    maxflow+=a[t];
    mincost+=dis[t]*a[t];
    for(int i=t;i!=s;i=pv[i]){
        edge[pe[i]].flow+=a[t];
        edge[pe[i]^1].flow-=a[t];
    }
    return true;
}
void kkkk(){
    while(bellmanford(s,t)){continue;}
    return;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        if(n==0&& m==0){return 0;}
        getchar();inint();
        for(int i=0;i<n;i++){
            scanf("%s",mp[i]);
        }
        Hnum=0;mannum=0;
        map<int,int>num;int cnt=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(mp[i][j]=='H'){
                    H[Hnum++]=i*100+j;
                }
                else if(mp[i][j]=='m'){
                    man[mannum++]=i*100+j;
                }
            }
        }
        s=0;t=Hnum+mannum+1;maxflow=0;mincost=0;
        for(int i=0;i<Hnum;i++){
            for(int j=0;j<mannum;j++){
                if(num[H[i]]==0){
                    num[H[i]]=cnt++;
                }
                if(num[man[j]]==0){
                    num[man[j]]=cnt++;
                }
                add(num[H[i]],num[man[j]],1,abs(H[i]/100-man[j]/100)+abs(H[i]%100-man[j]%100));

            }
        }
        for(int i=0;i<Hnum;i++)add(s,num[H[i]],1,0);
        for(int j=0;j<mannum;j++)add(num[man[j]],t,1,0);
        kkkk();
        //cout<<maxflow<<endl;
        printf("%d\n",mincost);
    }
    return 0;
}
posted @ 2020-09-29 19:08  ouluy  阅读(88)  评论(0编辑  收藏  举报