题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费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. 关于小米手机USB传输稍大点的文件老中断的问题解决方法!

    关于小米手机USB传输稍大点的文件老中断的问题解决方法! 这是一个很痛苦的事情,当你传输大文件的时候,传输到一半就会莫名其妙的中断,拔插数据线很多次以后,好不容易没准可以成功传输一次. 后来使用了36 ...

  2. 介绍我最近做的网站 Asp.Net MVC4 + BootStrap

    一.前言 最近一直在做一个多站SEO数据分析的站点(www.easyyh.com),用了一些新技术,如Asp.Net MVC4,BootStrap,EasyUI,这些都是以前没有搞过的,最近搞得差不多 ...

  3. Java基础:(一)数据类型

    一.包装类型 基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成. 八个基本类型:boolean/1:byte/8:char/16:short/16:int/32: ...

  4. ribbon hystrix仪表盘

    Circuit Breaker: Hystrix Dashboard (断路器:hystrix 仪表盘) 基于service-ribbon 改造下: pom.xml加入: <dependency ...

  5. Thread 和 Runnable创建新线程的区别,Runnable可以共享线程类的实例属性

    Thread实现多线程: public class Thread2 extends Thread{ public  int i; public void run(){ for(; i < 100 ...

  6. Jenkins上svn更新策略说明

  7. WEB网页如何让背景图片跟随可视窗口自适应大小

    HTML代码 <body id="body"> <div class="info-wrapper"> <div class=&qu ...

  8. 在2017年,如何将你的小米4刷上Windows 10 mobile?(后附大量图赏)

    众多攻略集大成者!资深软粉亲测有效! 参考教程: http://bbs.xiaomi.cn/t-11814358 http://bbs.xiaomi.cn/t-11736827 问:刷机前,我需要做什 ...

  9. windows 10 无法使用内置管理员账户打开应用的解决方案

    步骤 运行regedit.msc: 依次找到:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ ...

  10. 突然心血来潮,想写写我在java面试中遇到的事。作为一个应届生,我觉得我的情况都与大部分应届生是差不多的,希望你们能在这上面得到一些有用的

    面试过程吧,怎么说呢?从一开始接触面试到现在成功了几家,这中间我确实收获了许多,那我就从我第一次面试开始讲吧. 第一次面试是有人介绍过来的,总之还是有一位贵人相助,所以第一次面试时,面试官很好没有怎么 ...