hdu 1068 D - Girls and Boys【匈牙利算法】【第三周练习】【the first day】

本文介绍了一个基于大学学生间浪漫关系的研究问题,通过匈牙利算法找出最大不相交的匹配集合,进而计算出未匹配的人数。输入包含多个数据集,每个数据集描述一组学生的浪漫关系,目标是最优化地找到没有浪漫关系的学生数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

the second year of the university somebody started a study on the romantic relations between the students. The relation ��romantically involved�� is defined between one girl and one boy. For the study reasons it is necessary to find out the maximum set satisfying the condition: there are no two students in the set who have been ��romantically involved��. The result of the program is the number of students in such a set.

The input contains several data sets in text format. Each data set represents one set of subjects of the study, with the following description:

the number of students
the description of each student, in the following format
student_identifier:(number_of_romantic_relations) student_identifier1 student_identifier2 student_identifier3 ...
or
student_identifier:(0)

The student_identifier is an integer number between 0 and n-1, for n subjects.
For each given data set, the program should write to standard output a line containing the result.

An example is given in Figure 1.


Input

7
0: (3) 4 5 6
1: (2) 4 6
2: (0)
3: (0)
4: (2) 0 1
5: (1) 0
6: (2) 0 1
3
0: (2) 1 2
1: (1) 0
2: (1) 0


Output

5
2

题意:求未匹配的人的对数。输入n,将学生编号为0~n-1,输入n行,每行为学生编号start,匹配的学生数m,以及m个匹配的学生编号。

思路:用匈牙利算法求出最大匹配数,也就是最小顶点数,由于没有区分性别,所以会有重复,因此,需要将算出的最小顶点数/2,最后总顶点数-最小顶点数,就是未匹配的人的对数。


//匈牙利算法模板题 
#include<stdio.h>
#include<string.h>
#define N 2000
int book[N+10],match[N];
int path[N+10][N+10];
int n,m;

int dfs(int u)
{
	for(int i = 0; i < n; i ++)
	{
		if(!book[i]&&path[u][i])
		{
			book[i] = 1;//标记i为已经访问过 
			if(match[i] == -1||dfs(match[i]))//如果i没有匹配或者找到了新的匹配 
			{
				match[i] = u;
				return 1;
			}
		}
	}
	return 0;
}

int main()
{
	int t,start,end;
	char s1,s4,s2,s3;
	while(scanf("%d",&n)!=EOF)
	{
		memset(path,0,sizeof(path));
		memset(match,-1,sizeof(match));
		for(int i = 0; i < n; i ++)
		{
			scanf("%d%c%c%c%d%c",&start,&s1,&s4,&s2,&m,&s3);
			for(int j = 0; j < m; j ++)
			{
				scanf("%d",&end);
				path[start][end] = 1;
			}
		}
		int sum = 0;
		for(int i = 0; i < n; i ++)
		{
			memset(book,0,sizeof(book));//每次重新寻找增广路需要置为0 
			if(dfs(i))
				sum ++;
		}
		printf("%d\n",n-sum/2);//由于没有区分性别,所以会有重复 
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值