打卡信奥刷题(1068)用C++实现信奥 P1682 过家家

P1682 过家家

题目描述

2 n 2n 2n 个小学生来玩过家家游戏,其中有 n n n 个男生,编号为 1 1 1 n n n,另外 n n n 个女生,编号也是 1 1 1 n n n。每一个女生可以选择一个和她不吵嘴的男生来玩,除此之外,如果编号为 X X X 的女生的朋友(也是女生,且编号为 Y Y Y)不和编号为 Z Z Z 的男生吵嘴,那么 X X X 也可以选择 Z Z Z。此外,朋友关系是可以传递的,比如 a a a b b b 是朋友, b b b c c c 是朋友,那么我们可以认为 a a a c c c 也是朋友。注意,一个男生可以被多个女生选择为玩伴。

当每一位女生都选择了玩伴,那么他们会开始新一轮游戏。在每一轮后,每个女生都会开始去找一个新的男生做玩伴(以前没选过)。而且每一个女生最多能强制 k k k 个男生接受,无论他们以前是否吵嘴。

现在你的任务就是确定这 2 n 2n 2n 个小学生最多能玩几轮游戏。

输入格式

第一行有四个整数 n , m , k , f n,m,k,f n,m,k,f 3 ≤ n ≤ 250 3 \le n \le 250 3n250 0 < m < n 2 0 < m < n^{2} 0<m<n2 0 ≤ f < n 0 \le f < n 0f<n)。

n n n 表示有 2 n 2n 2n 个小学生,其中 n n n 个男生 n n n 个女生。

接下来 m m m 行,每行包含两个数字 a , b a,b a,b 表示编号为 a a a 的女生和编号为 b b b 的男生从没吵嘴过。

再接下来 f f f 行,每行包含两个数字 c , d c,d c,d 表示编号为 c c c 的女生和编号为 d d d 的女生是朋友。

输出格式

对于每组数据,输出一个整数,表示 2 n 2n 2n 个小学生最多能玩几轮。

输入输出样例 #1

输入 #1

4 5 1 2
1 1
2 3
3 2
4 2
4 4
1 4
2 3

输出 #1

3

C++实现

#include
#include
#define MAXN 100000
using namespace std;
int n,m,k,f,pre[MAXN],num[MAXN],ans=2147483647;
bool maps[500][500]; 
struct node{int from,to;
}edge1[MAXN],edge2[MAXN];
int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);} 
void merge(int x,int y)
{
	int fx=find(x),fy=find(y);
	if(fx!=fy)pre[fx]=fy;
}
int main()
{
	cin>>n>>m>>k>>f;
	for(int i=1;i<=n;i++)pre[i]=i;
	for(int i=1;i<=m;i++)cin>>edge1[i].from>>edge1[i].to; //女from 和 男to 从不吵架 
	for(int i=1;i<=f;i++)cin>>edge2[i].from>>edge2[i].to;  //女from 和 女to 是朋友 
	for(int i=1;i<=f;i++)merge(edge2[i].from,edge2[i].to);//朋友关系用并查集处理联通情况 
	for(int i=1;i<=m;i++)
		if(!maps[find(edge1[i].from)][edge1[i].to])       
			num[find(edge1[i].from)]++, 
			maps[find(edge1[i].from)][edge1[i].to]=true;
	for(int i=1;i<=n;i++)
		if(num[i])ans=min(ans,num[i]); //取最小 
	ans=min(ans+k,n); 
	cout<<ans<<endl;
}

打卡信奥刷题(1068)用C++实现信奥 P1682 过家家_第1张图片

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

你可能感兴趣的:(C++,c++,算法,开发语言,青少年编程,数据结构)