luogu3386 【模板】 二分图匹配

基本概念:二分图有两种节点:X节点和Y节点。如果X和Y可以匹配, 则X与Y连着一条边。每个X节点最多只能匹配一个Y节点,同时每个Y节点最多只能匹配一个X节点。最大匹配便是最多的匹配数。

交错路径:交错路径中的边分为重边和轻边。每个每两个相邻的边的种类是不同的。对于两端的边都为轻边的一条交错路径,此时如果把轻边变成重边,重边变成轻边(以后此操作简称翻转),路径上重边的数量便会多一个。

在二分图最大匹配中,一个X一个X地,看看以下通过Dfs实现的操作能否成功:把当前X节点当作起点,图中已经匹配的边为潜在的重边,去寻找一个未匹配过的Y节点。如果操作成功,将找到的交错路径一翻转,匹配的数量就多了一个。最后输出总匹配的数量即可。

注意:Dfs的Vis标记在Y里,而不在X里。

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

const int MAX_XNODE = 1010, MAX_YNODE = 1010, MAX_EDGE = MAX_XNODE*MAX_YNODE;
#define LOOP(i, n) for(int i=1; i<=n; i++)

struct Hungary
{
private:
	struct Xnode;
	struct Ynode;
	struct Edge;

	struct Xnode
	{
		Edge *Head;
	}_xNodes[MAX_XNODE];
	int _xCnt;

	struct Ynode
	{
		Xnode *Match;
		bool Vis;
	}_yNodes[MAX_YNODE];
	int _yCnt;

	struct Edge
	{
		Xnode *X;
		Ynode *Y;
		Edge *Next;
	}*_edges[MAX_EDGE];
	int _eCnt;

	Edge *NewEdge()
	{
		return _edges[++_eCnt] = new Edge();
	}

	bool Dfs(Xnode *x)
	{
		for (Edge *e = x->Head; e; e = e->Next)
		{
			if (!e->Y->Vis)
			{
				e->Y->Vis = true;
				if (!e->Y->Match || Dfs(e->Y->Match))
				{
					e->Y->Match = x;
					return true;
				}
			}
		}
		return false;
	}

public:
	Hungary(){}

	Hungary(int xCnt, int yCnt) :_xCnt(xCnt), _yCnt(yCnt), _eCnt(0)
	{
		memset(_xNodes, 0, sizeof(_xNodes));
		memset(_yNodes, 0, sizeof(_yNodes));
		memset(_edges, 0, sizeof(_edges));
	}

	void AddEdge(int xId, int yId)
	{
		Xnode *x = _xNodes + xId;
		Ynode *y = _yNodes + yId;
		Edge *e = NewEdge();
		e->X = x;
		e->Y = y;
		e->Next = x->Head;
		x->Head = e;
	}

	int GetMatchCnt()
	{
		int ans = 0;
		LOOP(xId, _xCnt)
		{
			LOOP(yId, _yCnt)
				_yNodes[yId].Vis = false;
			ans += Dfs(_xNodes + xId);
		}
		return ans;
	}
};

int main()
{
#ifdef _DEBUG
	freopen("c:\noi\source\input.txt", "r", stdin);
#endif
	int totX, totY, totE, xId, yId;
	scanf("%d%d%d", &totX, &totY, &totE);
	static Hungary g(totX, totY);
	while (totE--)
	{
		scanf("%d%d", &xId, &yId);
		if (xId > totX || yId > totY)
			continue;
		g.AddEdge(xId, yId);
	}
	printf("%d
", g.GetMatchCnt());
	return 0;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/8661079.html