poj2195 bfs+最小权匹配
题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费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+最小权匹配的更多相关文章
- HDU(1853),最小权匹配,KM
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Other ...
- Poj(3686),最小权匹配,多重匹配,KM
题目链接 The Windy's | Time Limit: 5000MS | Memory Limit: 65536K | | Total Submissions: 4939 | Accepted: ...
- POJ 3565 Ants (最小权匹配)
题意 给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案. 思路 一开始没想到怎么用最小权匹配--后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)--还是 ...
- UVALIVE 4970 最小权匹配
首先贴一下这道题的BNU地址,UVA地址自己找吧. http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=11852 题意:这道题的意思就是,给你N个棋子的 ...
- POJ 2400 最小权匹配
吐槽:首先,这道题的输入居然是错的.要将上下两个矩阵的位置换一下才可以出样例,也就是上面那个矩阵是employee对Supervisor的打分,下面那个矩阵才是Supervisor对employee的 ...
- poj 2516(拆点+最小权匹配)
题目链接:http://poj.org/problem?id=2516 思路:考虑某种货物,由于某个订货商可能接受来自不同地区的货物,而某一地区的货物也可能送给不同的订货商,显然不能直接进行匹配,必须 ...
- poj 3686(拆点+最小权匹配)
题目链接:http://poj.org/problem?id=3686 思路:显然工件为X集,机器为Y集合.由于每个机器一次只能加工一个部件,因此我们可以将一台机器拆成N个点,至于部件与机器之间连多大 ...
- poj 2195(KM求最小权匹配)
题目链接:http://poj.org/problem?id=2195 思路:我们都知道KM使用来求最大权匹配的,但如果要求最小权匹配,只需把图中的权值改为负值,求一次KM,然后权值和取反即可. ht ...
- 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
[POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS Memory Limit ...
随机推荐
- AXURE-手把手教你做汉化
我们默认下载的AXURE是英文版的,对于英文能力不足或者不习惯英文界面的,那必须使用汉化手段,网上也有很多朋友已经为大家做好了汉化文件,这里介绍一下如何自己做AXURE的汉化. 如何开始汉化 如何 ...
- 复习KMP
KMP刚学的时候,看不懂. 再看,哇!原来是这样! 用的时候,忘了. 为了不再跌倒,我决定,记住吧... 在我看来,KMP一般用于字符串匹配时的防超时优化. 他的精髓就是,利用已经匹配的信息,简化这之 ...
- 09SpringAopAdvice
Spring原生的经典模式 实现 AOP 通知: 前置通知:在目标方法执行之前执行,不能改变方法的执行流程和结果! 实现 MethodBeforeAdvice接口! 后置通知:在目标方法执行之后执行, ...
- Java热启动
1.在项目中的pom.xml中添加 <dependency> <groupId>org.springframework.boot</groupId> <art ...
- CF1166C A Tale of Two Lands
思路: 搞了半天发现和绝对值无关. http://codeforces.com/blog/entry/67081 实现: #include <bits/stdc++.h> using na ...
- FAST FW150R软件版本升级解决一些网页无法加载问题
家里用的移动宽带,通过无线路由器无线上网.上taobao.天猫都很快,但是一上京东.苏宁易购界面加载很慢,界面无法显示,怀疑是无线路由问题,然后直接通过网线相连接,发现问题消失,决定对无线路由软件版本 ...
- Intellij IDEA项目添加资源文件
添加了一个资源文件,但读取的时候出错了 prop.load(Config.class.getResourceAsStream("/resources/dbconfig.properties& ...
- Dictionary(支持 XML 序列化),注意C#中原生的Dictionary类是无法进行Xml序列化的
/// <summary> /// Dictionary(支持 XML 序列化) /// </summary> /// <typeparam name="TKe ...
- HDU 2149 Public Sale 拍卖(巴什博弈)
思路:只要能给对方留下n+1,我就能胜,否则败. #include <iostream> #include <cstdio> using namespace std; int ...
- self & this 上下文
对象:指向对象的首地址: 函数:代表了函数运行的主要上下文: 内部:在类的内部使用. self Within the body of a class method, self refers to th ...