1 条题解
-
0
自动搬运
来自洛谷,原作者为

NewSjf
**搬运于
2025-08-24 21:27:53,当前版本为作者最后更新于2019-08-23 18:43:36,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
楼下提到过可以用并查集来做,所以我来贡献一篇并查集的题解
用并查集基本上就是线性时间复杂度,而且代码少,也比较好理解
这道题我们男生和女生的关系与女生和女生之间的关系分开建图
最后大概能得到这么一副关系图

女生之间会形成几个联通快
同一个联通快中的任何一个女生都能选择连接到这个联通快的男生
例如最左边的那个联通快,因为每个女生每次选择不同的男生
可以看出每个女生都有三种选择,因而游戏进行三轮
同理右边那个最多进行两轮
而中间那个孤立的点一轮都无法进行
但是题目中又说 每一个女生最多能强制k个男生接受
例如当k=2时候

游戏就能多进行两轮,那么这个孤立的点也能进行两轮游戏了
我们在计算答案的时候,先不考虑k,得到每个联通快能进行的游戏轮数
然后再取最小值,记为ans.
那么考虑k之后的最终答案就是min(ans+k,n)
具体代码如下,短小精悍#include<iostream> #include<cstring> #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]) //要记录每个联通快连接的不同编号的男生数目,用maps标记防止重复计数 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); //考虑k之后的答案,最大值有可能会超过n,这显然是不行的 cout<<ans<<endl; }
- 1
信息
- ID
- 672
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者