[35] Machine Schedule

//Sample Input
5 5 10
0 1 1
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 3
9 4 3
0
 

//Sample Output
3
 

题意:给出每个任务可以由机器a的x模式或机器b的y模式完成,机器调整模式需要重启,求最少重启数(起始模式均为0).

算法:Hungary

问题:学习匈牙利算法

思路: 最少顶点覆盖数就是最大匹配数;匈牙利算法寻找的过程使用dfs即可;可设左边为起点。(详见注释)

代码:ac

#include<bits/stdc++.h>
using namespace std;
/*求最少顶点覆盖数就是求最大匹配数*/
int con[510][510];/*连接关系*/
int vis[510];/*右边点使用与否*/
int link[510];/*右边点连接的左边点*/
int n, m, k;/*如题意*/
int dfs(int x)/*用以判断找不找得到结尾为之前未连的边的情况*/
{
	for (int y = 0; y < m; y++) {
		if (!vis[y] && con[x][y]) /*代表右边这个点在此轮没有使用过且可有连线*/
		{
			vis[y] = 1;/*标注已使用*/
			if (dfs(link[y])||link[y]==-1) /*代表要么这个点并未连过或者它的连线的点能找到另一个有未连的边的点……*/
			{
				link[y] = x;/*找到就重新连接*/
				return 1;
			}
		}
	}
	return 0;
}
int hungary()
{
	int res = 0;
	memset(link, -1, sizeof(link));/*注意连线是需要存储的,不然下一步就没有方向了*/
	for (int x = 0; x < n; x++) {
		memset(vis, 0, sizeof(vis));/*注意这是每轮清空,表示需要抢之前已经匹配的*/
		if (dfs(x))res++;/*成功一次多一个匹配数*/
	}
	return res;
}
int main()
{
	while (scanf("%d", &n), n) {
		scanf("%d%d", &m, &k);
		int id, x, y;
		memset(con, 0, sizeof(con));
		for (int i = 0; i < k; i++) {
			scanf("%d%d%d", &id, &x, &y);
			if (x && y)con[x][y] = 1;/*左右均为0时为初始情况,不产生影响*/
		}
		printf("%d\n", hungary());
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值