题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题。

这题就是建图有点麻烦,但绝不抽象,直接用BFS遍历每个人到所有房子的距离,遍历出一个就拉一条人到房子有向边,建完图就是套模板了。

注意:KM算法是求最大权匹配的,要求最小权就要把所有边取相反数,最后结果再取相反数,但这只能是完美匹配,不完美匹配还要变一些。

 #include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
#define maxn 500 using namespace std; char group[][];
int index[][];
struct pos
{
int x,y;
}people[maxn],house[maxn];
struct edge
{
int to,cap;
};
vector<edge> g[maxn];
int a,b,sum_m,sum_h; const int mir[][]={{,},{,-},{,},{-,}};
int vis[][];
struct step
{
int x,y,s;
};
void init()
{
sum_m=sum_h=;
memset(people,,sizeof(people));
memset(house,,sizeof(house));
memset(index,,sizeof(index));
for(int i=;i<maxn;i++)
g[i].clear();
}
void add_edge(int from,int to,int cap)
{
g[from].push_back((edge){to,cap});
}
void bfs(int sx,int sy,int ex,int ey)
{
memset(vis,,sizeof(vis));
step now,next;
queue<step> q;
now.x=sx,now.y=sy,now.s=;
vis[sx][sy]=;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
if(now.x==ex&&now.y==ey)
{
add_edge(index[sx][sy],index[now.x][now.y],~now.s+);
return;
}
for(int i=;i<;i++)
{
int x=now.x+mir[i][];
int y=now.y+mir[i][];
if(x>=&&y>=&&x<a&&y<b)
{
if(!vis[x][y])
{
vis[x][y]=;
next.x=x,next.y=y,next.s=now.s+;
q.push(next);
}
}
}
}
}
int x[maxn], y[maxn], link[maxn],sx[maxn], sy[maxn];
int slack;
int DFS(int t)
{
int i, tmp;
sx[t] = ;
for (i = ; i < g[t].size(); i++)
{
edge e=g[t][i];
if (!sy[e.to])
{
tmp = x[t] + y[e.to] - e.cap;
if (tmp == )
{
sy[e.to] = ;
if (link[e.to] == - || DFS(link[e.to]))
{
link[e.to] = t;
return ;
}
}
else if (tmp < slack)
slack = tmp;
}
}
return ;
}
void KM()
{
int i, j;
for(int w=;w<sum_m;w++)
{
x[w]=;
for(int v=;v<g[w].size();v++)
{
if(g[w][v].cap>x[w])
x[w]=g[w][v].cap;
}
}
for (j = ; j < sum_h; j++)
{
y[j] = ;
}
memset(link, -, sizeof(link));
for (i = ; i < sum_m; i++)
{
while ()
{
memset(sx, , sizeof(sx));
memset(sy, , sizeof(sy));
slack = 0xfffffff;
if (DFS(i)) break;
for (j = ; j < sum_m; j++)
{
if (sx[j])
x[j] -= slack;
}
for (j = ; j < sum_h; j++)
{
if (sy[j])
y[j] += slack;
}
}
}
} int main()
{
while(scanf("%d%d",&a,&b)!=EOF,a&&b)
{
getchar();
init();
for(int i=;i<a;i++)
{
gets(group[i]);
for(int j=;j<b;j++)
{
if(group[i][j]=='m')
{
people[sum_m].x=i;
people[sum_m].y=j;
index[i][j]=sum_m;
sum_m++;
}
else if(group[i][j]=='H')
{
house[sum_h].x=i;
house[sum_h].y=j;
index[i][j]=sum_h;
sum_h++;
}
}
}
for(int n=;n<sum_m;n++)
{
for(int m=;m<sum_h;m++)
{
bfs(people[n].x,people[n].y,house[m].x,house[m].y);
}
}
/* for(int i=0;i<sum_m;i++)
{
cout<<i<<" ";
for(int j=0;j<g[i].size();j++)
cout<<g[i][j].to<<" "<<g[i][j].cap<<endl;
}*/
KM();
int ans=;
int coun = ,t=;
for (int i = ; i < sum_h; i++)
{
t = link[i];
if (t >= )
{
coun ++;
ans += g[t][i].cap;
}
}
printf("%d\n",~ans+);
}
return ;
}

poj2195 bfs+最小权匹配的更多相关文章

  1. HDU(1853),最小权匹配,KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...

  2. Poj(3686),最小权匹配,多重匹配,KM

    题目链接 The Windy's | Time Limit: 5000MS | Memory Limit: 65536K | | Total Submissions: 4939 | Accepted: ...

  3. POJ 3565 Ants (最小权匹配)

    题意 给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案. 思路 一开始没想到怎么用最小权匹配--后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)--还是 ...

  4. UVALIVE 4970 最小权匹配

    首先贴一下这道题的BNU地址,UVA地址自己找吧. http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=11852 题意:这道题的意思就是,给你N个棋子的 ...

  5. POJ 2400 最小权匹配

    吐槽:首先,这道题的输入居然是错的.要将上下两个矩阵的位置换一下才可以出样例,也就是上面那个矩阵是employee对Supervisor的打分,下面那个矩阵才是Supervisor对employee的 ...

  6. poj 2516(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=2516 思路:考虑某种货物,由于某个订货商可能接受来自不同地区的货物,而某一地区的货物也可能送给不同的订货商,显然不能直接进行匹配,必须 ...

  7. poj 3686(拆点+最小权匹配)

    题目链接:http://poj.org/problem?id=3686 思路:显然工件为X集,机器为Y集合.由于每个机器一次只能加工一个部件,因此我们可以将一台机器拆成N个点,至于部件与机器之间连多大 ...

  8. poj 2195(KM求最小权匹配)

    题目链接:http://poj.org/problem?id=2195 思路:我们都知道KM使用来求最大权匹配的,但如果要求最小权匹配,只需把图中的权值改为负值,求一次KM,然后权值和取反即可. ht ...

  9. 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)

    [POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS   Memory Limit ...

随机推荐

  1. VS2010/VS2013项目创建及通过ADO.NET连接mysql/sql server步骤(VS2013连接成功步骤见上一篇随笔)

    本随笔主要是对初学者通过ADO.NET连接数据库的步骤(刚开始我也诸多不顺,所以总结下,让初学者熟悉步骤) 1.打开VS新建一个项目(这里的VS版本不限,建项目都是一样的步骤) VS2010版本如图: ...

  2. 关于编译错误ambiguous call of overridden pre R14 auto-imported BIF get/1

    今天写代码用到了进程字典,出现了一个编译错误 根据相关提示改成了erlang:put erlang/get以后即编译通过

  3. Redis hash(哈希)

    Redis hash可储存多个键值对,适合储存对象的属性. 1.hset key fieldName fileValue    //hset即hash set,set这里是设置的意思.往hash中添加 ...

  4. ABAP系统字段

    SY是一个全局的结构体变量,在词典中已定义过.输入SE11到ABAP字典中. 输入SYST点击显示 附录D 系统字段功能列表 字段名 类型 长度 应用目的 说明 ABCDE CHAR 26 常量 字母 ...

  5. ae(ArcEngine) java swing开发入门系列(2):ae的类型转换和Proxy类说明

    做过C#版ae的都知道,操作同一个“对象”,用他的不同功能要转换到相应的接口,但java版有时不能直接做类型转换 例如下图在C#是可以的 但在java不行,这样转会报错,看IFeatureClass的 ...

  6. SQL Server数据库log shipping 灾备(Part1 )

    1.概述 Log Shipping为SQL Server提供的数据库备份过程.它可以将数据库整个复制到另一台服务器上.在这种情况下,交易日志也会定期发送到备份服务器上供恢复数据使用,这使得服务器一直处 ...

  7. Python使用easy-install安装时报UnicodeDecodeError的解决方法

    Python使用easy-install安装时报UnicodeDecodeError的解决方法,有需要的朋友可以参考下. 问题描述: 在使用easy-install安装matplotlib.pypar ...

  8. ZOJ 3469 Food Delivery (区间DP,经典)

    题意: 在x轴上有一家外卖餐馆,有n个顾客站在x轴上不同坐标上且叫了外卖,每个人的脾气不同,每1分钟没有收到外卖就会增加Fi点愤怒值,而外卖小哥的车是有速度的v-1/分钟,问怎样的送餐次序会让所有顾客 ...

  9. Erlang程序设计(第2版)读书笔记(一)

    正如<代码的未来>中所说,为了充分利用多核,并发变成将成为未来发展的趋势,对于并发编程的支持,Erlang确实是不二之选,Erlang在国内仍然较为小众,经典书籍相对也要少很多,最终选择了 ...

  10. 换个语言学一下 Golang (3)——数据类型

    在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. Go 语言按类别有以下几种 ...