hdu 2063 二分图匹配

效率较高:

#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

typedef struct node
{
	int ord;
	node * next;
}Node;

const int size = 512+1;

Node list[size];
int X[size];
int Y[size];
bool visit[size];
int size_x;
int size_y;
stack <int> stk;
void init()
{
	int i;
	for(i=1;i<=size;i++)
		list[i].next = NULL;
	memset(X,0,(size_x+1)*sizeof(int));
	memset(Y,0,(size_y+1)*sizeof(int));
}

void input(int len)
{
	int i;
	int x;
	int y;
	Node *p;
	for(i=0;i<len;i++)
	{
		scanf("%d%d",&x,&y);
		p = new Node;
		p->ord=y;
		p->next = list[x].next; //邻接表存储
		list[x].next=p;
	}
}

bool dfs(int x)
{
	Node *p;
	stk.push(x);
	for(p=list[x].next;p;p=p->next)
	{
		if(!visit[p->ord])
		{
			visit[p->ord] = true;
			stk.push(p->ord);
			if(!Y[p->ord] || dfs(Y[p->ord]))
				return true;
			else
				stk.pop();
		}
	}
	stk.pop();
	return false;
}


void solve()
{
	int i ;
	int top;
	for(i=1;i<=size_x;i++)
	{
		while(!stk.empty())
			stk.pop();
		memset(visit,false,size_y+1);
		if(dfs(i))
		{
			while(!stk.empty())
			{
				top=stk.top();
				stk.pop();
				Y[top] = stk.top();
				X[stk.top()] = top;
				stk.pop();
			}
		}
	}	
}

void output()
{
	int i ;
	int count=0;
	Node * p;
	for(i=1;i<=size_x;i++)
	{
		if(X[i]) count++;
		while(p=list[i].next)
		{
			list[i].next=p->next;
			delete p;
		}
	}
	cout<<count<<endl;
}

int main()
{
	int n ;
	while(scanf("%d",&n),n)
	{
		scanf("%d%d",&size_x,&size_y);
		init();
		input(n);
		solve();
		output();

		while(!stk.empty())
			stk.pop();
	}
	return 0;
}



帮助理解:

#include<iostream>
#include<stdio.h>
#include <memory.h>
using namespace std;
#define MAX 505
int map[MAX][MAX],flag[MAX];
int pre[MAX];
int n,m,num;

int find(int cur)
{
	int i;
	for(i=1;i<=m;i++)//m是男生的个数
	{
		if(map[cur][i]&&!flag[i])//如果说这个男生和女生可以坐在一起而且这个男生在实验当中没有被任何女生占领
		{
			flag[i]=1;//标记这个男生在实验当中被占领
			if(pre[i]==-1||find(pre[i]))//如果这个男生没有被占领,或者通过增广路径,让拥有这个男生的女生找到啦新欢
			{
				pre[i]=cur;//女生cur拥有这个男生
				return 1;//因为找到,所以就这样做啦。返回1
			}
		}
	}
	return 0;//这个女孩始终找不到增广路
}

int main()
{
	//freopen("in.txt","r",stdin);
	int i,girl,boy,sum;
	while(scanf("%d",&num),num)
	{
		//初始化
        memset(map, 0, sizeof(map));
        memset(pre, -1, sizeof(pre));sum = 0;

		//输入部分
		scanf("%d %d",&n,&m);
        for(i = 0; i < num; i++)
        {
            scanf("%d %d", &girl, &boy);
            map[girl][boy] = 1;  //可以匹配
        }

		//开始匹配
        for(i = 1; i <= n; i++)     //女生去匹配男生
        {
             memset(flag, 0, sizeof(flag)); //每次重新标记0
             sum += find(i);
        }
        printf("%d\n", sum);
        
	}
	return 0;
}

/*

1 这个问题可以很容易的翻译一下:从第女生3查找的时候,发现男生1已经被女生2拥有啦,那么就让女生2去查找一个新的男生,
2 现在的问题是flag的就是标记每一次当中匹配和不匹配的男生。所以每一次都应该初始化
3 return 0表示,通过增广路径找不到新的。

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值