http://acm.hdu.edu.cn/showproblem.php?pid=1533
给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个"$H$"的最小花费
思路:
实际上应该是一道KM匹配的题,不过也可以转化为费用流
建立附加源汇点,$m$连接源点,$H$连接汇点,其余建立$num(H)*num(m)$条边,容量为1,费用为曼哈顿距离,跑一边费用流就行....
#include <bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pp pair<int,int> #define rep(ii,a,b) for(int ii=a;ii<=b;ii++) #define per(ii,a,b) for(int ii=a;ii>=b;ii--) #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(a,b) cout<<#a<<'['<<b<<"]="<<b[a]<<endl using namespace std; const int maxn=1e5+10; const int maxm=1e6+10; const int INF=0x3f3f3f3f; int casn,n,m,k; struct node { int pre,to,cap,cost,next; }e[maxm]; int head[maxn],nume,inq[maxn],sum,ans; int q[maxn],pre[maxn],dis[maxn]; int num[maxn],ss,tt; inline void addx(int a,int b,int c,int d){ e[++nume]={a,b,c,d,head[a]}; head[a]=nume; } inline void add(int a,int b,int c,int d){ addx(a,b,c,d);addx(b,a,0,-d); } bool spfa(int s=ss,int t=tt){ for(int i=0;i<=t;i++)dis[i]=INF; dis[s]=q[0]=s; int top=0,end=1; while(top!=end){ int now=q[top++];top%=maxn; for(int i=head[now];i;i=e[i].next){ int to=e[i].to; if(e[i].cap&&dis[to]>dis[now]+e[i].cost){ pre[to]=i; dis[to]=dis[now]+e[i].cost; if(!inq[to]){ inq[e[i].to]=true; if(dis[to]<dis[q[top]]){ top=(top==0)?maxn-1:top-1; q[top]=to; }else{ q[end++]=to;end%=maxn; } } } } inq[now]=false; } return dis[t]!=INF; } void dfs(int s=ss,int t=tt){ int flow=INF; for(int i=pre[t];i;i=pre[e[i].pre]) flow=min(flow,e[i].cap); for(int i=pre[t];i;i=pre[e[i].pre]) { e[i].cap-=flow; e[i^1].cap+=flow; ans+=e[i].cost*flow; } } int hh[123][2]; int mm[123][2]; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); #endif IO; while(cin>>n>>m,n+m){ nume=1; int cnt1=0,cnt2=0; char ch; memset(head,0,sizeof head); nume=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>ch; if(ch=='m') { mm[++cnt1][0]=i; mm[cnt1][1]=j; } if(ch=='H') { hh[++cnt2][0]=i; hh[cnt2][1]=j; } } } ss=0,tt=cnt1+cnt2+1; for(int i=1;i<=cnt1;i++){ add(ss,i,1,0); for(int j=1;j<=cnt2;j++){ add(i,j+cnt1,1,abs(hh[j][0]-mm[i][0])+abs(hh[j][1]-mm[i][1])); } } for(int i=1;i<=cnt2;i++){ add(i+cnt1,tt,1,0); } ans=0; while(spfa())dfs(); cout<<ans<<endl; } #ifdef test fclose(stdin);fclose(stdout);system("out.txt"); #endif return 0; }