(网络流 匹配 KM) Going Home --poj -- 2195
链接:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82835#problem/D
有n个人有n栋房子,每栋房子里能进一个人,但每走一格的价值是1, 所以要尽可能的少走,这一看很显然是匹配用KM算法,
但这是网络流专题的,不是太懂怎么用网络流来写
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std; #define N 110
#define INF 0x3fffffff struct node{int x, y, step;}; char G[N][N];
int n, m1, dir[][]={{-,},{,},{,-},{,}};
int STEP[N][N], m[N][N], H[N][N], vis[N][N];
int num1, num2, lx[N], ly[N];
int used[N], visx[N], visy[N], s[N]; void BFS(node p)
{
node q, t;
queue<node>Q;
Q.push(p); memset(vis, , sizeof(vis));
vis[p.x][p.y] = ; while(Q.size())
{
q = Q.front(); Q.pop(); if(G[q.x][q.y]=='H')
STEP[m[p.x][p.y]][H[q.x][q.y]] = -q.step; for(int i=; i<; i++)
{
t.x = q.x + dir[i][];
t.y = q.y + dir[i][];
t.step = q.step + ; if(t.x>= && t.x<n && t.y>= && t.y<m1 && !vis[t.x][t.y])
{
Q.push(t);
vis[t.x][t.y] = ;
}
}
}
}
bool Find(int u)
{
visx[u] = ;
for(int i=; i<=num2; i++)
{
if(!visy[i] && lx[u]+ly[i]==STEP[u][i])
{
visy[i] = ;
if(!used[i] || Find(used[i]))
{
used[i] = u;
return true;
}
}
else
s[i] = min(s[i], lx[u]+ly[i]-STEP[u][i]);
}
return false;
}
void KM()
{
memset(used, , sizeof(used));
memset(lx, , sizeof(lx));
memset(ly, , sizeof(ly)); for(int i=; i<=num1; i++)
for(int j=; j<=num2; j++)
lx[i] = max(lx[i], STEP[i][j]); for(int i=; i<=num1; i++)
{
for(int j=; j<=num2; j++)
s[j] = INF;
while()
{
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy)); if(Find(i))
break; int d = INF;
for(int j=; j<=num2; j++)
if(!visy[j])
d = min(d, s[j]); for(int j=; j<=num2; j++)
{
if(visx[j])
lx[j] -= d;
if(visy[j])
ly[j] += d;
}
}
}
int res = ; for(int i=; i<=num1; i++)
res -= STEP[used[i]][i]; printf("%d\n", res);
} int main()
{
while(scanf("%d%d", &n, &m1), n+m1)
{
int i, j;
node p; num1=, num2=;
memset(STEP, , sizeof(STEP));
for(i=; i<n; i++)
{
scanf("%s", G[i]);
for(j=; j<m1; j++)
{
if(G[i][j]=='m')
m[i][j] = ++num1;
if(G[i][j]=='H')
H[i][j] = ++num2;
}
} for(i=; i<n; i++)
for(j=; j<m1; j++)
{
if(G[i][j]=='m')
{
p.x=i, p.y=j, p.step=;
BFS(p);
}
} KM();
}
return ;
}
粘个别人的代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<math.h>
using namespace std; const int MAXN = ;
const int oo = 1e9+; struct point{int x, y;}man[MAXN], house[MAXN];
struct Graph{int flow, cost;}G[MAXN][MAXN];
int NX, NY, start, End;///男人和房子的数目,源点和汇点 bool spfa(int pre[])
{
stack<int> sta;
int instack[MAXN]={}, dist[MAXN]; for(int i=; i<=End; i++)
dist[i] = oo; dist[start] = ;
sta.push(start); while(sta.size())
{
int u = sta.top();sta.pop();
instack[u] = false; for(int i=; i<=End; i++)
{
if(G[u][i].flow && dist[i] > dist[u]+G[u][i].cost)
{
dist[i] = dist[u] + G[u][i].cost;
pre[i] = u; if(instack[i] == false)
{
sta.push(i);
instack[i] = true;
}
}
}
} return dist[End] != oo;
}
int MinCost()
{
int i, pre[MAXN], cost=; while(spfa(pre) == true)
{///如果有增广路
int MinFlow = oo; for(i=End; i != start; i=pre[i])
MinFlow = min(MinFlow, G[pre[i]][i].flow);
for(i=End; i != start; i=pre[i])
{///逆向访问这条增广路上的每条边
int k = pre[i];
G[k][i].flow -= MinFlow;
G[i][k].flow += MinFlow;
cost += G[k][i].cost;
}
} return cost;
} int main()
{
int M, N; while(scanf("%d%d", &M, &N), M+N)
{
int i, j;char s[MAXN][MAXN]; memset(G, , sizeof(G));
NX = NY = ; for(i=; i<M; i++)
scanf("%s", s[i]); for(i=; i<M; i++)
for(j=; j<N; j++)
{
if(s[i][j] == 'm')
{
NX++;
man[NX].x = i;
man[NX].y = j;
}
if(s[i][j] == 'H')
{
NY++;
house[NY].x = i;
house[NY].y = j;
}
} for(i=; i<=NX; i++)
for(j=; j<=NY; j++)
{///房子的编号从NX~NX+NY
G[i][NX+j].flow = ;
G[i][NX+j].cost = fabs(man[i].x-house[j].x)+fabs(man[i].y-house[j].y);
G[NX+j][i].cost = -G[i][NX+j].cost;
} start = NX+NY+, End = start+; for(i=; i<=NX; i++)
{///把源点与人连接
G[start][i].flow = ;
G[start][i].cost = ;
}
for(i=; i<=NY; i++)
{///把房子和汇点连接
G[NX+i][End].flow = ;
G[NX+i][End].cost = ;
} printf("%d\n", MinCost());
} return ;
}
(网络流 匹配 KM) Going Home --poj -- 2195的更多相关文章
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submiss ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- POJ 2195 Going Home / HDU 1533(最小费用最大流模板)
题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...
- POJ 2195 Going Home 最小费用最大流 尼玛,心累
D - Going Home Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Subm ...
- 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- poj 2195 Going Home(最小费最大流)
poj 2195 Going Home Description On a grid map there are n little men and n houses. In each unit time ...
- hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)
Cyclic Tour Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total ...
- 训练指南 UVALive - 4043(二分图匹配 + KM算法)
layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...
随机推荐
- Java操作Excel之Poi
package com.java1234.poi; import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSF ...
- html5中的SessionStorage 和localStorage
html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage. sessionStorage用于本地存储一个会话(session)中的数据,这些数据只 ...
- SQL 数据库主键 ,外键
主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个 ...
- express + mongodb 搭建一个简易网站 (五)
前面已经将导航中的“所有宝贝”页面连上了mongodb,现在我们就把其他的页面脸上数据库,将整个网站全部实现. 打开routes文件,找到jacket.js,将里面的代码修改如下: var expre ...
- debug-stripped.ap_' specified for property 'resourceFile' does not exist.(转载)
1.错误描述 更新Android Studio到2.0版本后,出现了编译失败的问题,我clean project然后重新编译还是出现抑郁的问题,问题具体描述如下所示: Error:A problem ...
- Java RSA 生成公钥 私钥
目前为止,RSA是应用最多的公钥加密算法,能够抵抗已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. RSA算法中,每个通信主体都有两个钥匙,一个公钥(Public Key)用来对数据进行加密 ...
- 在Windows下远程连接CentOS6
远程连接linux服务器的方式:以显示的类型来分类,可以分为字符界面和图形界面两种.字符界面软件有SecureCRT.PUTTY等:图形界面有Xmanager.Xdmcp和VNC软件等.
- clamp 函数
返回范围内的一个数值.可以使用 clamp 函数将不断增加.减小或随机变化的数值限制在一系列的值中. float clamp(float minnumber, float maxnumber, flo ...
- 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr
auto_ptr<string> p1(new string ("auto") : //#1 auto_ptr<string> p2; //#2 p2 = ...
- 二叉树的层次遍历 · Binary Tree Level Order Traversal
[抄题]: 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) [思维问题]: [一句话思路]: 用queue存每一层 [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况 ...