题意

Frank是一个思想有些保守的高中老师。有一次,他需要带一些学生出去旅行,但又怕其中一些学生在旅行中萌生爱意。为了降低这种事情发生的概率,他决定确保带出去的任意两个学生至少要满足下面四条中的一条。

1.身高相差大于40厘米

2.性别相同

3.最喜欢的音乐属于不同类型

4.最喜欢的体育比赛相同

你的任务是帮助Frank挑选尽量多的学生,使得任意两个学生至少满足上述条件中的一条。

分析

这个模型叫二分图的最大独立集。既选择尽量多的结点,使得任意两个结点不相邻(既任意一条边的两个端点不会被同时选中)。最大独立集与最小覆盖是互补的,因此答案就是结点总数减去最大匹配数。

建模:将每个人看作一个结点,如果两个人四个条件都不满足,就意味着他们不能同时被选择,连一条无向边。这样,问题就转换为求这个图的最大独立集。因为他们每个人不是男生就是女生,所以这个图是二分图。

按照惯例,我依然是用网络流来做的最大匹配。原因依然是不会KM···等哪天(8012年)我学会来并且心情好可能会来补一下KM的代码。

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <cmath>
  6. #include <queue>
  7.  
  8. using namespace std;
  9. const int maxn=+;
  10. const int maxm=+;
  11.  
  12. const int INF=;
  13. struct Dinic{
  14. int head[maxn],Next[maxm],to[maxm],cap[maxm],flow[maxm];
  15. int sz,n,m,s,t;
  16. bool vis[maxn];
  17. int cur[maxn],d[maxn];
  18. void init(int n){
  19. this->n=n;
  20. memset(head,-,sizeof(head));
  21. this->sz=-;
  22. }
  23. void add_edge(int a,int b,int c){
  24. ++sz;
  25. to[sz]=b;
  26. cap[sz]=c;flow[sz]=;
  27. Next[sz]=head[a];head[a]=sz;
  28. ++sz;
  29. to[sz]=a;
  30. cap[sz]=c;flow[sz]=c;
  31. Next[sz]=head[b];head[b]=sz;
  32. }
  33. bool BFS(){
  34. memset(vis,,sizeof(vis));
  35. queue<int>Q;
  36. vis[s]=;
  37. d[s]=;
  38. Q.push(s);
  39. while(!Q.empty()){
  40. int u=Q.front();Q.pop();
  41. for(int i=head[u];i!=-;i=Next[i]){
  42. int v=to[i];
  43. if(!vis[v]&&cap[i]>flow[i]){
  44. vis[v]=;
  45. d[v]=d[u]+;
  46. Q.push(v);
  47. }
  48. }
  49. }
  50. return vis[t];
  51. }
  52. int DFS(int x,int a){
  53. if(x==t||a==)return a;
  54. int Flow=,f;
  55. for(int& i=cur[x];i!=-;i=Next[i]){
  56. int v=to[i];
  57. if(d[v]==d[x]+&&(f=DFS(v,min(a,cap[i]-flow[i])))>){
  58. Flow+=f;
  59. flow[i]+=f;
  60. flow[i^]-=f;
  61. a-=f;
  62. if(a==)break;
  63. }
  64. }
  65. return Flow;
  66. }
  67. int Maxflow(int s,int t){
  68. this->s=s,this->t=t;
  69. int Flow=;
  70. while(BFS()){
  71. for(int i=;i<=n;i++)
  72. cur[i]=head[i];
  73.  
  74. Flow+=DFS(s,INF);
  75. }
  76. return Flow;
  77. }
  78. }dinic;
  79. int T,n;
  80. int high[maxn];
  81. char sex[maxn];
  82. string mus[maxn],phy[maxn];
  83. int main(){
  84. scanf("%d",&T);
  85. for(int t=;t<=T;t++){
  86. scanf("%d",&n);
  87. for(int i=;i<=n;i++){
  88. scanf("%d %c",&high[i],&sex[i]);
  89. cin>>mus[i]>>phy[i];
  90. }
  91. dinic.init(n+);
  92. for(int i=;i<=n;i++){
  93. if(sex[i]=='M'){
  94. for(int j=;j<=n;j++){
  95. if(sex[j]=='F'&&abs(high[i]-high[j])<=&&mus[i]==mus[j]&&phy[i]!=phy[j]){
  96. dinic.add_edge(i,j,);
  97. }
  98. }
  99. }
  100. }
  101. for(int i=;i<=n;i++){
  102. if(sex[i]=='M')
  103. dinic.add_edge(,i,);
  104. }
  105. for(int i=;i<=n;i++){
  106. if(sex[i]=='F')
  107. dinic.add_edge(i,n+,);
  108. }
  109. int ans=dinic.Maxflow(,n+);
  110. printf("%d\n",n-ans);
  111. }
  112. return ;
  113. }

其实我觉得这道题不知道这个模型只是考虑最小割的话也能想。去除最少的学生使得剩下的所有学生之间任意两个之间都满足四个条件中的一条。我们在学生之间连的边是这两个学生间只能选一个或者都不选,那个割掉这条边就代表去掉这两个学生中的一个。所以可以求出最小割来以后,用总的人数n减掉最小割。

哇万能的最小割我感觉这样想比背什么模型好多了啊!

【LA3415 训练指南】保守的老师 【二分图最大独立集,最小割】的更多相关文章

  1. 训练指南 UVA - 11419(二分图最小覆盖数)

    layout: post title: 训练指南 UVA - 11419(二分图最小覆盖数) author: "luowentaoaa" catalog: true mathjax ...

  2. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  3. 二分图&网络流&最小割等问题的总结

    二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...

  4. hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)

    要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值 分析:二分图带权最大独立集. 用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, ...

  5. 【LA4043 训练指南】蚂蚁 【二分图最佳完美匹配,费用流】

    题意 给出n个白点和n个黑点的坐标,要求用n条不相交的线段把他们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接一条线段. 分析 结点分黑白,很容易想到二分图.其中每个白点对应一个X结 ...

  6. 训练指南 UVALive - 3523 (双联通分量 + 二分图染色)

    layout: post title: 训练指南 UVALive - 3523 (双联通分量 + 二分图染色) author: "luowentaoaa" catalog: tru ...

  7. 【UVA11419 训练指南】我是SAM 【二分图最小覆盖,最小割】

    题意 给出一个R*C大小的网格,网格上面放了一些目标.可以在网格外发射子弹,子弹会沿着垂直或者水平方向飞行,并且打掉飞行路径上的所有目标.你的任务是计算最少需要多少子弹,各从哪些位置发射,才能把所有目 ...

  8. 【LA3523 训练指南】圆桌骑士 【双连通分量】

    题意 有n个骑士经常举行圆桌会议,商讨大事.每次圆桌会议至少应有3个骑士参加,且相互憎恨的骑士不能坐在圆桌旁的相邻位置.如果发生意见分歧,则需要举手表决,因此参加会议的骑士数目必须是奇数,以防赞同和反 ...

  9. 训练指南 UVALive - 3126(DAG最小路径覆盖)

    layout: post title: 训练指南 UVALive - 3126(DAG最小路径覆盖) author: "luowentaoaa" catalog: true mat ...

随机推荐

  1. Automating CSS Regression Testing

    The following is a guest post by Garris Shipon . We've touched on the four types of CSS testing here ...

  2. TCP和UDP通信(C#网络编程) ---- 系列文章

    文章系列目录 C#网络编程系列文章(一)之Socket实现异步TCP服务器 C#网络编程系列文章(二)之Socket实现同步TCP服务器 C#网络编程系列文章(三)之TcpListener实现异步TC ...

  3. PAT1034. Head of a Gang ——离散化+并查集

    题意:成员A与成员B通话 ,成员B与成员C通话,则 ABC即为一个团伙,一共有若干个团伙,每个团伙的人数大于2且相互通话时间超过一定值即为黑帮,每个黑帮伙里有一个BOSS,boss是与各个成员打电话最 ...

  4. CentOS部署NetCore - 3. 部署站点

    一. CentOS 安装FTP linux 安装 ftp第一步 使用如下命令#rpm -qa |grep vsftpd可以检测出是否安装了vsftpd软件, 如果没有安装,使用YUM命令进行安装. y ...

  5. 免费数据集下载网站【dataset】

    https://github.com/awesomedata/awesome-public-datasets

  6. php常用字符串数组函数

    Php常用的数组函数 键值操作 Array_values($arr) 获取数据的值 Array_keys($arr) 获取数组的key Array_flip($arr) 数组键值反转 In_array ...

  7. 【AR实验室】mulberryAR :添加连续图像作为输入

    本文转载请注明出处 —— polobymulberry-博客园 0x00 - 前言 之前mulberryAR只能利用手机相机实时捕捉图像作为系统的输入,这也比较符合用户的习惯.但是在开发的过程中,有时 ...

  8. EasyUI 左,右(上、下)布局

    左,右(上.下)布局 <body class="easyui-layout"> <div data-options="region:'west',col ...

  9. org.hibernate.Session常用方法的作用总结

    clear(): 清理session缓存.把所有加载出来的持久化实例都从session缓存中清除,同时,也会挂掉当前session中正在排队的save,update,delete操作. evict: ...

  10. Tkinter学习

    from tkinter import * window = Tk() # 创建一个窗口 window.mainloop() # 消息循环,显示窗口 window.title("窗口标题&q ...