二分图匹配 - 学习心得

发布时间 2023-10-08 17:19:35作者: q(x)

就是跑匈牙利算法就行了,难点完全在于建图。

模板水题

Link

#include <bits/stdc++.h>
const int N=510;
int n,m,e;
int G[N][N],match[N];
std::bitset<N> vis;

namespace BlackWhiteGraph{
	inline void Init(void){
		scanf("%d%d",&n,&m);
		int a,t;
		for(register int i=1;i<=n;++i){
			scanf("%d",&t);
			while(t--)
				scanf("%d",&a),
				G[i][a]=1;
		}
	}
	bool dfs(int u){
		for(register int i=1;i<=m;++i){
			if(!vis[i]&&G[u][i]){
				vis[i]=true;
				if(!match[i]||dfs(match[i])){
					match[i]=u;
					return true;
				}
			}
		}
		return false;
	}
	int ans=0;
	void Match(void){
		for(register int i=1;i<=n;++i){
			vis.reset();
			if(dfs(i))++ans;
		}
	}
	void output(void){
		printf("%d\n",ans);
		exit(0);
	}
}

using namespace BlackWhiteGraph;
int main(){
	Init();
	Match();
	output();
}

直接无脑套板子然后无脑匈牙利就 \(AC\) 了。

#include <bits/stdc++.h>
#define add push_back
using namespace std;
const int N=10100;
int n,m;
vector<int> G[N];
int match[N],use[N];
bitset<N> vis;
bool dfs(int u){
	for(int v : G[u]){
		if(!vis[v]){
			vis[v]=true;
			if(!match[v] || dfs(match[v])){
				use[u]=v,match[v]=u;
				return true; 
			}	
		}
	}
	return false;
}
int main(){
	int ans=0;
	scanf("%d%d",&m,&n);
	int a,b;
	scanf("%d%d",&a,&b);
	while(a!=-1&&b!=-1){
		G[a].add(b);
		scanf("%d%d",&a,&b);
	}
	for(register int i=1;i<=n;++i){
		vis.reset();
		ans+=dfs(i);
	}
	printf("%d\n",ans);
	for(register int i=1;i<=n;++i){
		if(use[i])
			printf("%d %d\n",i,use[i]);
	}
	exit(0);
}

相比于上一道题这道题要记录路径,因为匈牙利模板自带存储路径,直接输出就行了,为什么这个东西也能进\(24\)

稍带思维的省选题

四川省选 \(Day2\ T3\),但是水得很,直接把两个属性和物品绑在一起然后一步一步跑匈牙利就 \(AC\).

但是这道题还是有一些细节什么的,要匈牙利比较熟悉原理才能 \(AC\).

#include "bits/stdc++.h"
#define ll long long
#define add push_back
using namespace std;
const int N=1e6+10;
int n,m,col;
int vis[N],match[N];
vector<int> G[N];
bool dfs(int u){
	for(int v:G[u])
		if(vis[v]!=col){
			vis[v]=col;
			if(!match[v] || dfs(match[v])){
				match[v]=u;
				return true;
			}
		}
	return false;
}
int main(){
	scanf("%d",&n);
	int mx=-1;
	for(register int i=1;i<=n;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].add(i);
		G[v].add(i);
	}
	for(register int i=1;i<N;++i){
		++col;if(!dfs(i)){
			printf("%d\n",col-1);
			break;
		}
	}
	
	return 0;
}

P2319 [HNOI2006] 超级英雄

上一题输出路径 \(AC\)

很难很难的省选题

鸽。