【链接】http://acm.hdu.edu.cn/showproblem.php?pid=1533
【题意】
一个N*M地图上有相同数量的字符H和字符m,m代表一个 人,H代表一个房子。人到房子的花销是它们在图中的曼哈顿距离,问你让所有人回到房子所需要的最小费用(一个房子只能容纳一个人)。
【题解】
费用流;
建立一个超级源点,它和每个房子都有一条边相连,边的容量为1,费用为0;
建立一个超级汇点,他和每个人都有一条边相连,边的容量为1,费用为0;
每个房子和每个人都有一条边,容量为1,费用为它们的曼哈顿距离
这个图的最大流肯定是房子的个数.
则这个时候跑一下最小费用最大流就好.
则这个时候跑一下最小费用最大流就好.
【错的次数】
0
【反思】
第一次写费用流
【代码】
#include <bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define LL long long #define rep1(i,a,b) for (int i = a;i <= b;i++) #define rep2(i,a,b) for (int i = a;i >= b;i--) #define mp make_pair #define pb push_back #define fi first #define se second #define ms(x,y) memset(x,y,sizeof x) #define ri(x) scanf("%d",&x) #define rl(x) scanf("%lld",&x) #define rs(x) scanf("%s",x) #define oi(x) printf("%d",x) #define ol(x) printf("%lld",x) #define oc putchar(' ') #define os(x) printf(x) #define all(x) x.begin(),x.end() #define Open() freopen("F:\rush.txt","r",stdin) #define Close() ios::sync_with_stdio(0) typedef pair<int,int> pii; typedef pair<LL,LL> pll; const int dx[9] = {0,1,-1,0,0,-1,-1,1,1}; const int dy[9] = {0,0,0,-1,1,-1,1,-1,1}; const double pi = acos(-1.0); const int N = 100; const int NN = 3e4; const int INF = 0x3f3f3f3f; struct abc{ int from,en,flow,nex,cost; }; int n,m,totm,fir[2*N+50],dis[N*2+50],pre[2*N+50],mi[2*N+50],ans; char s[N+10][N+10]; vector <pii> H,M; abc bian[NN]; bool inq[2*N+50]; queue <int> dl; void add(int x,int y,int flow,int cost){ bian[totm].nex = fir[x]; fir[x] = totm; bian[totm].from = x; bian[totm].en = y; bian[totm].cost = cost; bian[totm].flow = flow; totm++; bian[totm].nex = fir[y]; fir[y] = totm; bian[totm].from = y; bian[totm].en = x; bian[totm].cost = -cost; bian[totm].flow = 0; totm++; } bool spfa(int s,int t){ ms(dis,INF),ms(inq,0),ms(mi,INF); dis[s] = 0,inq[s] = 1; dl.push(s); pre[t] = -1; while (!dl.empty()){ int x = dl.front(); inq[x] = false; dl.pop(); for (int i = fir[x];i!=-1;i = bian[i].nex){ int y = bian[i].en; if (bian[i].flow && dis[y] > dis[x] + bian[i].cost){ dis[y] = dis[x] + bian[i].cost; mi[y] = min(bian[i].flow,mi[x]); pre[y] = i; if (!inq[y]){ inq[y] = true; dl.push(y); } } } } if (pre[t]==-1) return false; int now = t; while (now != s){ int temp = pre[now]; bian[temp].flow -= mi[t]; bian[temp^1].flow += mi[t]; now = bian[temp].from; ans += mi[t]*bian[temp].cost; } return true; } int main(){ //Open(); //Close(); while (~ri(n)){ ans = 0; ri(m); if (n == 0 && m == 0) break; rep1(i,0,n-1) rs(s[i]); H.clear(),M.clear(); rep1(i,0,n-1) rep1(j,0,m-1) if (s[i][j]=='H') H.pb(mp(i,j)); else if (s[i][j]=='m') M.pb(mp(i,j)); totm = 0; ms(fir,255); int len1 = H.size(),len2 = M.size(); rep1(i,0,len1-1) add(0,i+1,1,0); rep1(i,0,len2-1) add(i+1+len1,len1+len2+1,1,0); rep1(i,0,len1-1) rep1(j,0,len2-1) add(i+1,len1+j+1,1,abs(M[j].fi-H[i].fi)+abs(M[j].se-H[i].se)); while (spfa(0,len1+len2+1)); oi(ans);puts(""); } return 0; }