poj 2195 二分图最优匹配 或 最小费用最大流
就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们manhattan距离。然后对所有权值取反,求一次最大二分图最优匹配,在将结果取反就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Maxn 110
using namespace std;
int n;//点的数目
int lx[Maxn],ly[Maxn]; //顶点标号
int weight[Maxn][Maxn];// 边的权值
int slack[Maxn];// Y(i)的松弛函数
int sx[Maxn],sy[Maxn]; //标记X,Y中的顶点是否在交错路径上
int match[Maxn];//Y的匹配
struct Point{
int x,y;
}house[Maxn],man[Maxn];
int Dis(Point a,Point b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
int dfs(int u)
{
sx[u]=;
int i;
for(i=;i<=n;i++)
{
if(!sy[i]&&lx[u]+ly[i]==weight[u][i])//如果在相等子图中,且未被访问
{
sy[i]=;
if(match[i]==-||dfs(match[i]))
{
match[i]=u;
return ;
}
}
else
if(!sy[i])//Y(i)不在交错路径当中
slack[i]=min(slack[i],lx[u]+ly[i]-weight[u][i]);
}
return ;
}
int bestmatch(bool f)
{
int i,j;
if(!f)
{
for(i=;i<=n;i++)
{
lx[i]=-0x7FFFFFFF;
ly[i]=;
for(j=;j<=n;j++)
{
weight[i][j]=-weight[i][j];
lx[i]=max(lx[i],weight[i][j]);
}
}
}
else
{
for(i=;i<=n;i++)
{
lx[i]=;
ly[i]=;
for(j=;j<=n;j++)
lx[i]=max(lx[i],weight[i][j]);
}
}
memset(match,-,sizeof(match));
for(i=;i<=n;i++)
while()
{
memset(sx,,sizeof(sx));
memset(sy,,sizeof(sy));
for(j=;j<=Maxn-;j++)
slack[j]=0x7FFFFFFF;
if(dfs(i))
break;
int dx=0x7FFFFFFF;
for(j=;j<=n;j++)
dx=min(dx,slack[j]);
for(j=;j<=n;j++)
{
if(sx[j])
lx[j]-=dx;
if(sy[j])
ly[j]+=dx;
}
}
int ans=;
for(i=;i<=n;i++)
ans+=weight[match[i]][i];
if(!f)
ans=-ans;
return ans;
}
int main()
{
int i,j,N,M,a,b;
char str[];
while(scanf("%d%d",&N,&M),N||M)
{
a=b=;
for(i=;i<=N;i++)
{
scanf("%s",&str);
for(j=;j<M;j++)
{
if(str[j]=='H')
house[++a].x=i,house[a].y=j;
if(str[j]=='m')
man[++b].x=i,man[b].y=j;
}
}
n=a;
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
weight[i][j]=Dis(man[i],house[j]);
}
printf("%d\n",bestmatch(false));
}
return ;
}
最小费油最大流解法:
#include<iostream>
#include<cstring>
#include<cstring>
using namespace std;
const int size = ;
const int INF = 0x7fffffff;
struct Point{
int x,y;
};
struct Edge
{
int to;
int vol;
int cost;
int next;
}e[size*];
Point house[],man[];
int index[size];
int edgeNum;
int pre[size], pos[size];
int dis[size], que[size*];
bool vis[size];
void insert(int from, int to, int vol, int cost)
{
e[edgeNum].to = to;
e[edgeNum].vol = vol;
e[edgeNum].cost = cost;
e[edgeNum].next = index[from];
index[from] = edgeNum++;
e[edgeNum].to = from;
e[edgeNum].vol = ;
e[edgeNum].cost = -cost;
e[edgeNum].next = index[to];
index[to] = edgeNum++;
}
int DIS(Point p1,Point p2)
{
return abs(p1.x-p2.x)+abs(p1.y-p2.y);
}
bool spfa(int s, int t)
{
int i;
memset(pre, -, sizeof(pre));
memset(vis, , sizeof(vis));
int head, tail; head = tail = ;
for(i = ; i < size; i++)
dis[i] = INF;
que[tail++] = s;
pre[s] = s;
dis[s] = ;
vis[s] = ;
while(head != tail)
{ int now = que[head++];
vis[now] = ;
for(i = index[now]; i != -; i = e[i].next)
{
int adj = e[i].to;
if(e[i].vol > && dis[now] + e[i].cost < dis[adj])
{
dis[adj] = dis[now] + e[i].cost;
pre[adj] = now;
pos[adj] = i;
if(!vis[adj])
{
vis[adj] = ;
que[tail++] = adj;
}
}
}
}
return pre[t] != -;
}
int MinCostFlow(int s, int t, int flow)
{
int i;
int cost = ;
flow = ;
while(spfa(s, t))
{
int f = INF;
for(i = t; i != s; i = pre[i])
if (e[pos[i]].vol < f) f = e[pos[i]].vol;
flow += f; cost += dis[t] * f;
for(i = t; i != s; i = pre[i])
{
e[pos[i]].vol -= f;
e[pos[i] ^ ].vol += f;
}
}
return cost; // flow是最大流值
}
int main()
{
int n,m,i,j,u,v;
char c;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==&&m==)
break;
memset(index,-,sizeof(index));
int k1=,k2=;
for(i=;i<=n;i++)
{
for(j=;j<=m;j++)
{
cin>>c;
switch(c)
{
case '.':break;
case 'm':man[++k1].x=i,man[k1].y=j;break;
case 'H':house[++k2].x=i,house[k2].y=j;break;
}
}
}
for(i=;i<=k1;i++)
{ for(j=;j<=k2;j++)
{
insert(i,j+k1,,DIS(man[i],house[j]));
}
insert(,i,,);
insert(i+k1,k1+k2+,,);
}
//spfa(0,k1+k2+1);
int ans=MinCostFlow(,k1+k2+,);
printf("%d\n",ans);
}
return ;
}
poj 2195 二分图最优匹配 或 最小费用最大流的更多相关文章
- POJ 2195 Going Home / HDU 1533(最小费用最大流模板)
题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...
- POJ 2135 Farm Tour (网络流,最小费用最大流)
POJ 2135 Farm Tour (网络流,最小费用最大流) Description When FJ's friends visit him on the farm, he likes to sh ...
- POJ2195 Going Home —— 最大权匹配 or 最小费用最大流
题目链接:https://vjudge.net/problem/POJ-2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total ...
- POJ 3686:The Windy's(最小费用最大流)***
http://poj.org/problem?id=3686 题意:给出n个玩具和m个工厂,每个工厂加工每个玩具有一个时间,问要加工完这n个玩具最少需要等待的平均时间.例如加工1号玩具时间为t1,加工 ...
- POJ 3422 Kaka's Matrix Travels 【最小费用最大流】
题意: 卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下.矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和. 思路: 最小费用最大流的题 ...
- poj 3565 二分图最优匹配
思路: 将ant与tree之间用距离来做权值,求最小权匹配就可以了.可以想到,如果有两条线段相交,那么将这两个线段交换一个顶点,使其不相交,其权值和一定会更小. 就像斜边永远比直角边长一样的道理. # ...
- POJ 3422 Kaka's Matrix Travels(最小费用最大流)
http://poj.org/problem?id=3422 题意 : 给你一个N*N的方格,每个格子有一个数字,让你从左上角开始走,只能往下往右走,走过的数字变为0,走K次,问最大能是多大,累加的. ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- POJ 2195:Going Home(最小费用最大流)
http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...
随机推荐
- 在Android4.0中Contacts拨号盘界面剖析(源码)
通过在 ViewPager 的适配器对象中,发现过一下三行代码 private DialpadFragment mDialpadFragment; private CallLogFragment ...
- Algorithms Part 1-Question 6- 2SUM Median-数和以及中位数问题
本次有两个编程问题,一个是求两个数的和满足一定值的数目,另一个是求中位数. 2SUM问题 问题描述 The goal of this problem is to implement a variant ...
- Connection对象连接加密2
一般情况下,大多数人习惯于将数据库连接写在web.config上里面,理论上讲,将明文存放在该文件里面是安全的,因为web.config文件是不允许被客户端下载,但一旦该文件泄漏出去,哪怕是很短的时间 ...
- jeewx的使用_02 解析微信服务器post过来的数据
如果在微信公众号接入了第三方的URL,那么用户微信服务器的请求将会被推送到第三方的URL上面,那么该如何解析数据呢?下面来分析 找到MessageUtil.java 这个类中有一个parseXml的静 ...
- Node.js和mybatis分别实现mysql中like变量模糊查询
<!-- mybatis --> <where> <if test="varName != '' and varName != null" > ...
- UVa10562 Undraw the Trees
注意点: 空树情况处理. >= && buf[r+][i-]=='-') i--; #include<cstdio> #include<cstring> ...
- 80端口被NT kernel & System 占用pid 4
前段时间停止了Apache,结果在打开的时候发现无法打开,80端口被占用,于是win+r 运行cmd 输入netstat -ano 可以看到80端口被PID4占用,于是打开任务管理器-进程-查看,选择 ...
- Codeforces Gym 100286G Giant Screen 水题
Problem G.Giant ScreenTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/con ...
- Oracle使用goldengate分别向Oracle和mysql双路的单向复制
一.Oracle分别向Oracle和mysql双路的单向复制是在: ORACLE-mysql的单向复制基础上做的.http://blog.csdn.net/q947817003/article/det ...
- ListView 文件重命名
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Control ...