您的位置:首页 > 其它

【二分图匹配】最大匹配-匈牙利算法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写法

/*匈牙利算法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);
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐