【二分图匹配】最大匹配-匈牙利算法BFS && DFS写法
2014-03-27 21:26
375 查看
搞了两节课终于搞懂了ORZ
这个讲解得很详细http://blog.csdn.net/pi9nc/article/details/11848327
注意:每次找增广路之前都要初始化
BFS写法要多加一个Prev数组保存这个点从哪个点来(同侧)
如果给出的两个点集各自序号都是1~n的: 对于DFS写法 因为其隐形地调用了一个栈 只要开一个Matchine数组记录一侧的匹配;
对于BFS写法 必须开两个Matchine数组
如果给出的点集只有一组序号= =就只要开一个了233 如果两个集合序号互有穿插,可以都下去找一遍,匹配数/2
比如下面HDU2444
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 210
bool flag;
int i,n,m,color[maxn],map[maxn][maxn],matchine[maxn],mark[maxn],ans;
void dfs(int now,int x){
for (int i=1;i<=n;i++){
if (map[now][i]){
if (!color[i]) {
color[i]=3-x;
dfs(i,3-x);
}
else if (color[i]==x) {
flag=false;
return;
}
if (flag==false) return;
}
}
}
bool check(){
memset(color,0,sizeof(color));
color[1]=1;
flag=true;
dfs(1,1);
return flag;
}
bool find(int now){
for (int j=1;j<=n;j++)
if (map[now][j] && !mark[j]){
mark[j]=1;
if (matchine[j]==-1 || find(matchine[j])){
matchine[j]=now;
// matchine[now]=j;
return true;
}
}
return false;
}
void maxto(){
ans=0;
memset(matchine,-1,sizeof(matchine));
for (int i=1;i<=n;i++)
{
memset(mark,0,sizeof(mark));
if (find(i)) ans++;
}
}
int main(){
while (scanf("%d",&n)!=EOF){
scanf("%d",&m);
memset(map,0,sizeof(map));
int x,y;
for (i=1;i<=m;i++){
scanf("%d%d",&x,&y);
map[x][y]=map[y][x]=1;
}
if (!check()) printf("No\n");
else {
maxto();
printf("%d\n",ans>>1);
}
}
}
奶牛分配(stall4.pas/in.out)(usaco 4.2)
描述
农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。
给出奶牛们的爱好的信息,计算最大分配方案。
输入格式
第一行 两个整数,N (0 <= N <= 200) 和 M (0 <= M <= 200) 。N 是农夫约翰的奶牛数量,M 是新牛棚的牛栏数量。
第二行到第N+1行 一共 N 行,每行对应一只奶牛。第一个数字 (Si) 是这头奶牛愿意在其中产奶的牛栏的数目 (0 <= Si <=M) 。后面的 Si 个数表示这些牛栏的编号。牛栏的编号限定在区间 (1..M) 中,在同一行,一个牛栏不会被列出两次。
输出格式
只有一行。输出一个整数,表示最多能分配到的牛栏的数量。
SAMPLE INPUT
5 5
2 2 5
3 2 3 4
2 1 5
3 1 2 5
1 2
SAMPLE OUTPUT
4
DFS写法
Hdu2063过山车
BFS写法
这个讲解得很详细http://blog.csdn.net/pi9nc/article/details/11848327
注意:每次找增广路之前都要初始化
BFS写法要多加一个Prev数组保存这个点从哪个点来(同侧)
如果给出的两个点集各自序号都是1~n的: 对于DFS写法 因为其隐形地调用了一个栈 只要开一个Matchine数组记录一侧的匹配;
对于BFS写法 必须开两个Matchine数组
如果给出的点集只有一组序号= =就只要开一个了233 如果两个集合序号互有穿插,可以都下去找一遍,匹配数/2
比如下面HDU2444
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 210
bool flag;
int i,n,m,color[maxn],map[maxn][maxn],matchine[maxn],mark[maxn],ans;
void dfs(int now,int x){
for (int i=1;i<=n;i++){
if (map[now][i]){
if (!color[i]) {
color[i]=3-x;
dfs(i,3-x);
}
else if (color[i]==x) {
flag=false;
return;
}
if (flag==false) return;
}
}
}
bool check(){
memset(color,0,sizeof(color));
color[1]=1;
flag=true;
dfs(1,1);
return flag;
}
bool find(int now){
for (int j=1;j<=n;j++)
if (map[now][j] && !mark[j]){
mark[j]=1;
if (matchine[j]==-1 || find(matchine[j])){
matchine[j]=now;
// matchine[now]=j;
return true;
}
}
return false;
}
void maxto(){
ans=0;
memset(matchine,-1,sizeof(matchine));
for (int i=1;i<=n;i++)
{
memset(mark,0,sizeof(mark));
if (find(i)) ans++;
}
}
int main(){
while (scanf("%d",&n)!=EOF){
scanf("%d",&m);
memset(map,0,sizeof(map));
int x,y;
for (i=1;i<=m;i++){
scanf("%d%d",&x,&y);
map[x][y]=map[y][x]=1;
}
if (!check()) printf("No\n");
else {
maxto();
printf("%d\n",ans>>1);
}
}
}
奶牛分配(stall4.pas/in.out)(usaco 4.2)
描述
农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术。不幸的是,由于工程问题,每个牛栏都不一样。第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶。上个星期,农夫约翰刚刚收集到了奶牛们的爱好的信息(每头奶牛喜欢在哪些牛栏产奶)。一个牛栏只能容纳一头奶牛,当然,一头奶牛只能在一个牛栏中产奶。
给出奶牛们的爱好的信息,计算最大分配方案。
输入格式
第一行 两个整数,N (0 <= N <= 200) 和 M (0 <= M <= 200) 。N 是农夫约翰的奶牛数量,M 是新牛棚的牛栏数量。
第二行到第N+1行 一共 N 行,每行对应一只奶牛。第一个数字 (Si) 是这头奶牛愿意在其中产奶的牛栏的数目 (0 <= Si <=M) 。后面的 Si 个数表示这些牛栏的编号。牛栏的编号限定在区间 (1..M) 中,在同一行,一个牛栏不会被列出两次。
输出格式
只有一行。输出一个整数,表示最多能分配到的牛栏的数量。
SAMPLE INPUT
5 5
2 2 5
3 2 3 4
2 1 5
3 1 2 5
1 2
SAMPLE OUTPUT
4
DFS写法
/*匈牙利算法DFS找最大匹配*/ #include<cstdio> #include<cstring> using namespace std; int n,m,map[201][201]={0},matchine[201]={0},i; bool mark[201]; bool find(int a){ for (int j=1;j<=m;j++) if (map[j][a]&& !mark[j]){ mark[j]=true; if (!matchine[j]|| find(matchine[j])){ matchine[j]=a; return true; } } return false; } int main(){ freopen("stall4.in","r",stdin); freopen("stall4.out","w",stdout); scanf("%d%d",&n,&m); int si,x,j; for (i=1;i<=n;i++){ scanf("%d",&si); for (j=1;j<=si;j++){ scanf("%d",&x); map[x][i]=1; // map[x][i]=1; 只需连一边 } } int ans=0; for (i=1;i<=n;i++){ memset(mark,0,sizeof(mark)); if (find(i)) ans++; } printf("%d\n",ans); }
Hdu2063过山车
BFS写法
#include<cstdio> #include<cstring> #include<queue> using namespace std; #define maxn 510 int point[maxn*2],next[maxn*2],last[maxn],ans,i,x,y,k,m; int prev[maxn],check[maxn],matchinex[maxn],n,matchiney[maxn]; queue<int >q; void work(){ memset(check,-1,sizeof(check)); memset(matchinex,-1,sizeof(matchinex)); memset(matchiney,-1,sizeof(matchiney)); //memset(prev,-1,sizeof(prev)); ans=0; for (int i=1;i<=m;i++) if (matchinex[i]==-1){ prev[i]=-1; while (!q.empty()) q.pop(); q.push(i); bool find=false; while (!q.empty() && !find){ int u=q.front(); q.pop(); for (int j=last[u];j&& !find;j=next[j]){ //注意&!find int v=point[j]; if (check[v]!=i){ check[v]=i; q.push(matchiney[v]); if (matchiney[v]>=0){// prev[matchiney[v]]=u; } else { find=true; int d=u,e=v; while (d!=-1){ int tmp=matchinex[d]; matchinex[d]=e; matchiney[e]=d; e=tmp; d=prev[d]; } } } } } if (matchinex[i]!=-1) ans++; } } int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); while (scanf("%d",&k) && k){ scanf("%d%d",&m,&n); memset(point,0,sizeof(point)); memset(next,0,sizeof(next)); memset(last,0,sizeof(last)); for (i=1;i<=k;i++){ scanf("%d%d",&x,&y); point[i]=y; next[i]=last[x]; last[x]=i; } work(); printf("%d\n",ans); } }
相关文章推荐
- HDOJ 2063 过山车【匈牙利算法求二分图最大匹配 DFS增广 BFS增广】
- 【二分图|最大匹配】POJ-3041 Asteroids(匈牙利算法dfs、bfs版)
- HDU2444 二分图判断(BFS 的染色法) + 求最大匹配边数(DFS 的匈牙利算法)
- 最大二分匹配 匈牙利算法模板&&POJ 1469 COURSES
- 二分图匹配匈牙利算法(DFS, BFS两种实现模板)
- 二分图的最大匹配、完美匹配和匈牙利DFS算法
- 二分图的最大匹配、完美匹配和匈牙利算法(转自Renfei Song's Blog)
- PKU 2584 - T-Shirt Gumbo (二分图最大匹配 & 匈牙利算法 | 最大流 & EK)
- USACO-Section 4.2 The Perfect Stall (二分图最大匹配[匈牙利算法[DFS]||网络流[Ford-Fulkerson]])
- 二分图匹配之最大匹配——匈牙利算法
- HDU - 1150 Machine Schedule 最小点覆盖(最大二分图匹配-匈牙利算法)邻接表写法
- 二分图最大匹配(匈牙利算法Dfs模板)
- 过山车 hdu2063 匹配、匈牙利算法起步&&最大流
- 【二分图匹配入门专题1】F - COURSES poj1469【最大匹配--匈牙利算法模板题】
- 二分图最大匹配---匈牙利算法BFS 实现
- 【二分图最大匹配】【匈牙利算法】poj1469 COURSES && poj2446 Chessboard
- 【二分图匹配】最大二分匹配——匈牙利算法
- 二分图最大匹配(匈牙利算法-DFS增广模板)
- nyoj 239 月老的难题 【二分图&&最大匹配&&匈牙利算法】
- poj2446 Chessboard 二分图最大匹配 思考 匈牙利算法BFS实现