您的位置:首页 > 编程语言 > Go语言

POJ 2195 Going Home(最小费用最大流)

2013-02-25 17:11 369 查看
题目链接

最小费用最大流算法 就好像是EK的变形。bfs的时候类似spfa找最短路,更新cost。

因为我是从 EK 的代码基础上改的,然后没发现if(u == end) break;和这个不一样。。。一直WA,注意数组开大一点。

先搜到的不一定是最优结果啊!!!

最小费用 最大流 邻接表模版。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x7fffffff
int low[1001],path[1001];
struct node
{
int u,v,w,next,re,cost;
}edge[501*201];
int first[1001],dis[1001],in[1001];
int str,end,n,m,t;
char ch[501][501];
struct point
{
int x,y;
}queh[1001],quem[1001];
int Abs(int a)
{
return a >= 0?a:-a;
}
void CL()
{
t = 1;
memset(first,-1,sizeof(first));
}
void add(int u,int v,int w,int cost)
{
edge[t].u = u;
edge[t].v = v;
edge[t].w = w;
edge[t].re = t+1;
edge[t].cost = cost;
edge[t].next = first[u];
first[u] = t ++;

edge[t].u = v;
edge[t].v = u;
edge[t].w = 0;
edge[t].re = t-1;
edge[t].cost = -cost;
edge[t].next = first[v];
first[v] = t ++;
}
int bfs()
{
int u,v,i;
memset(path,-1,sizeof(path));
for(i = 0;i <= end;i ++)
{
dis[i] = INF;
in[i] = 0;
}
queue<int> que;
que.push(str);
in[str] = 1;
dis[str] = 0;
low[str] = INF;
while(!que.empty())
{
u = que.front();
in[u] = 0;
que.pop();
for(i = first[u]; i != -1; i = edge[i].next)
{
v = edge[i].v;
if(edge[i].w&&dis[v] > dis[u] + edge[i].cost)
{
low[v] = low[u] < edge[i].w ? low[u]:edge[i].w;
path[v] = i;
dis[v] = dis[u] + edge[i].cost;
if(!in[v])
{
que.push(v);
in[v] = 1;
}
}
}
}
if(path[end] == -1)
return -1;
else
return low[end];
}
int mcmf()
{
int ans = 0,res,now,temp;
while((res = bfs()) != -1)
{
now = end;
while(now != str)
{
temp = path[now];
edge[edge[temp].re].w += res;
edge[temp].w -= res;
ans += res*edge[temp].cost;
now = edge[temp].u;
}
}
return ans;
}
int build()
{
int i,j,numh = 1,numm = 1;
for(i = 0;i < n;i ++)
{
for(j = 0;j < m;j ++)
{
if(ch[i][j] == 'm')
{
quem[numm].x = i;
quem[numm].y = j;
numm ++;
}
else if(ch[i][j] == 'H')
{
queh[numh].x = i;
queh[numh].y = j;
numh ++;
}
}
}
numm --;
numh --;
for(i = 1;i <= numm;i ++)
{
for(j = 1;j <= numh;j ++)
{
int d;
d = Abs(quem[i].x-queh[j].x)+Abs(quem[i].y-queh[j].y);
add(i,numm+j,1,d);
}
}
for(i = 1;i <= numm;i ++)
{
add(0,i,1,0);
}
for(i = 1;i <= numm;i ++)
{
add(numm+i,2*numm+1,1,0);
}
return 2*numm;
}
int main()
{
int i;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n == 0&&m == 0) break;
CL();
for(i = 0;i < n;i ++)
scanf("%s",ch[i]);

str = 0;end = build()+1;
printf("%d\n",mcmf());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: