匈牙利算法(dfs,bfs)

dfs

#include<iostream>
#include<queue>
using namespace std;
//X
const int N = 205;
//Y
const int M = 205;
//line[i][j]代表i到j有边,只存i->j的,没有存j到i的
bool line[N][M];
//是否访问过
bool visit[M];
//y连接的x(从右到左)
int my[M];
int n, m;
bool Find(int x) {
	for (int i = 1; i <= n; ++i) {
		//有边,且没被访问过
		if (line[x][i] && !visit[i]) {
			visit[i] = true;
			//如果是没有被连接,或者可以调整出位置
			if (my[i] == 0 || Find(my[i])) {
				my[i] = x;
				return true;
			}
		}
	}
	return false;
}
int Hungarian() {
	int cnt = 0;
	memset(my, 0, sizeof(my));
	for (int i = 1; i <= n; ++i) {
		memset(visit, false, sizeof(visit));
		if (Find(i)) {
			++cnt;
		}
	}
	return cnt;
}
int main() {
	while (~scanf("%d%d", &n, &m)) {
		memset(line, false, sizeof(line));
		for (int i = 1; i <= n; ++i) {
			int s;
			scanf("%d", &s);
			while (s--) {
				int t;
				scanf("%d", &t);
				line[i][t] = true;
			}
		}
		printf("%d\n", Hungarian());
	}
	return 0;
}

bfs

有一个不同的就是visit不再是每次memset成0而是在处理第i个点的时候,visit[y]=i代表被使用过了 

#include<iostream>
#include<queue>
using namespace std;
//X
const int N = 205;
//Y
const int M = 205;
//line[i][j]代表i到j有边,只存i->j的,没有存j到i的
bool line[N][M];
//x连接的y(从左到右)
int mx[N];
//y连接的x(从右到左)
int my[M];
//是否访问过
int visit[M];
//前驱,用来回溯的
int pre[N];
int n, m;
int Hungarian() {
	memset(mx, 0, sizeof(mx));
	memset(my, 0, sizeof(my));
	memset(visit, 0, sizeof(visit));
	int cnt = 0;
	for (int i = 1; i <= n; ++i) {
		//没有连接的y
		if (mx[i] == 0) {
			queue<int> q;
			q.push(i);
			pre[i] = -1;
			bool flag = false;
			while (!q.empty() && !flag) {
				int u = q.front();
				q.pop();
				//遍历u连接的边
				for (int v = 1; v <= m; ++v) {
					//有边,且y没被访问过
					if (line[u][v] && visit[v] != i) {
						visit[v] = i;
						//如果y被别人连了,就要调整对应的x
						if (my[v] > 0) {
							q.push(my[v]);
							pre[my[v]] = u;
						}
						else {
							//连接完了
							flag = true;
							//调整连接
							while (u != -1) {
								int temp = mx[u];
								mx[u] = v;
								my[v] = u;
								u = pre[u];
								v = temp;
							}
							break;
						}
					}
				}
			}
			if (mx[i] > 0) {
				++cnt;
			}
		}
	}
	return cnt;
}
int main() {
	while (~scanf("%d%d", &n, &m)) {
		memset(line, false, sizeof(line));
		for (int i = 1; i <= n; ++i) {
			int s;
			scanf("%d", &s);
			while (s--) {
				int t;
				scanf("%d", &t);
				line[i][t] = true;
			}
		}
		printf("%d\n", Hungarian());
	}
	return 0;
}
发布了93 篇原创文章 · 获赞 83 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39942341/article/details/103456075