有 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 3≤n≤250, 0 < m < n 2 0 < m < n^{2} 0<m<n2, 0 ≤ f < n 0 \le f < n 0≤f<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 个小学生最多能玩几轮。
4 5 1 2
1 1
2 3
3 2
4 2
4 4
1 4
2 3
3
#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;
}
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容