题意
题意很简单,给一张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
",mincost);
}
return 0;
}