0
点赞
收藏
分享

微信扫一扫

Going Home HDU - 1533

​​点击打开链接​​

费用流模板

一开始建的图太烂了 每个点和四周的点建边 其实只对m与H建边即可 边的费用即为两点曼哈顿距离

#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f

struct node1
{
int v;
int w;
int c;
int next;
};

struct node2
{
int x;
int y;
};

queue <int> que;
node1 edge[40010];
node2 pre1[10010],pre2[10010];
int first[10010],dis[10010],book[10010],pre[10010];
char mp[110][110];
int n,m,num,s,e,cnt1,cnt2;

void addedge(int u,int v,int w,int c)
{
edge[num].v=v;
edge[num].w=w;
edge[num].c=c;
edge[num].next=first[u];
first[u]=num++;
return;
}

void build()
{
int next[4][2]={0,-1,-1,0,0,1,1,0};
int i,j,k,tx,ty,u,v;
s=n*m+1,e=n*m+2,cnt1=0,cnt2=0;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(mp[i][j]=='m')
{
cnt1++;
pre1[cnt1].x=i;
pre1[cnt1].y=j;
}
else if(mp[i][j]=='H')
{
cnt2++;
pre2[cnt2].x=i;
pre2[cnt2].y=j;
}
}
}
memset(first,-1,sizeof(first));
num=0;
for(i=1;i<=cnt1;i++)
{
u=s,v=pre1[i].x*m+pre1[i].y+1;
addedge(u,v,1,0);
addedge(v,u,0,0);
}
for(i=1;i<=cnt2;i++)
{
u=pre2[i].x*m+pre2[i].y+1,v=e;
addedge(u,v,1,0);
addedge(v,u,0,0);
}
for(i=1;i<=cnt1;i++)
{
for(j=1;j<=cnt2;j++)
{
u=pre1[i].x*m+pre1[i].y+1,v=pre2[j].x*m+pre2[j].y+1;
addedge(u,v,1,abs(pre1[i].x-pre2[j].x)+abs(pre1[i].y-pre2[j].y));
addedge(v,u,0,-abs(pre1[i].x-pre2[j].x)-abs(pre1[i].y-pre2[j].y));
}
}
return;
}

int spfa()
{
int i,u,v,w,c;
while(!que.empty()) que.pop();
memset(dis,0x3f,sizeof(dis));
memset(book,0,sizeof(book));
memset(pre,-1,sizeof(pre));
que.push(s);
dis[s]=0,book[s]=1;
while(!que.empty())
{
u=que.front();
que.pop();
book[u]=0;
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v,w=edge[i].w,c=edge[i].c;
if(w>0&&dis[v]>dis[u]+c)
{
dis[v]=dis[u]+c,pre[v]=i;
if(!book[v])
{
que.push(v);
book[v]=1;
}
}
}
}
return dis[e];
}

int mcmf()
{
int res,i,u,v,w,c,cost,minn;
cost=0;
while(1)
{
res=spfa();
if(res==N) break;
cost+=res;
minn=N;
for(i=pre[e];i!=-1;i=pre[v])
{
v=edge[i^1].v,w=edge[i].w;
minn=min(minn,w);
}
for(i=pre[e];i!=-1;i=pre[v])
{
v=edge[i^1].v,c=edge[i].c;
edge[i].w-=minn;
edge[i^1].w+=minn;
}
}
return cost;
}

int main()
{
int i;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
for(i=0;i<n;i++)
{
scanf("%s",mp[i]);
}
build();
printf("%d\n",mcmf());
}
return 0;
}

 


举报

相关推荐

0 条评论