Description

有N个单身的男孩和N个单身女孩,男孩i和女孩j在一起得到的幸福值为Hij。一个匹配即对这N个男孩女孩的安排:

每个男孩恰好有一个女朋友,每个女孩恰好有一个男朋友。一个匹配的幸福值即这N对男女朋友的幸福值的和。经典的问题是计算幸福值最大的匹配,即完美匹配。然而完美匹配有时候并不唯一,你需要计算,对于所有的完美匹配,其交集是什么。

Input

输入的第一行是一个正整数N。N ≤ 80

接下来是一个N*N大小的矩阵H,Hij表示男孩i和女孩j在一起的幸福值。(0≤Hij≤5000)

Output

第一行输出完美匹配的幸福值

接下来是若干行,每一行是一对整数i和j,表示男孩i和女孩j在所有完美匹配的交集中。以i的递增顺序输出

Sample Input

3
1 1 1
2 1 1
1 1 1

Sample Output

4
2 1

Solution

数据范围够小
所以直接先跑一遍费用流,把集合中的边记下来
然后枚举这些边,把这些边从图中删掉,再跑费用流,如果跑出来的结果和最开始的结果一样,说明存在完美匹配不包括当前边,标记下来
最后存在集合里并且没有被标记的边就是答案

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=80+10,inf=0x3f3f3f3f;
int n,e=1,s,t,beg[MAXN<<1],cur[MAXN<<1],p[MAXN<<1],level[MAXN<<1],to[MAXN*MAXN*2],nex[MAXN*MAXN*2],cap[MAXN*MAXN*2],was[MAXN*MAXN*2],G[MAXN][MAXN],ans_was,vis[MAXN<<1],clk,out[MAXN*MAXN<<1],M[MAXN][MAXN],stand,cnt;
std::queue<int> q;
struct side{int x,y;inline bool operator < (const side &A) const {return x<A.x||(x==A.x&&y<A.y);};
};
side match[MAXN*MAXN],ans[MAXN*MAXN];
template<typename T> inline void read(T &x)
{T data=0,w=1;char ch=0;while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')w=-1,ch=getchar();while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+'0');if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y,int z,int k)
{to[++e]=y;nex[e]=beg[x];out[e]=x;beg[x]=e;cap[e]=z;was[e]=k;to[++e]=x;nex[e]=beg[y];out[e]=y;beg[y]=e;cap[e]=0;was[e]=-k;
}
inline void Build()
{e=1;memset(beg,0,sizeof(beg));for(register int i=1;i<=n;++i)for(register int j=1;j<=n;++j)if(~G[i][j])insert(i,j+n,1,-G[i][j]+5001);for(register int i=1;i<=n;++i)insert(s,i,1,0),insert(i+n,t,1,0);
}
inline bool bfs()
{memset(level,inf,sizeof(level));level[s]=0;p[s]=1;q.push(s);while(!q.empty()){int x=q.front();q.pop();p[x]=0;for(register int i=beg[x];i;i=nex[i])if(level[to[i]]>level[x]+was[i]&&cap[i]){level[to[i]]=level[x]+was[i];if(!p[to[i]])p[to[i]]=1,q.push(to[i]);}}return level[t]!=inf;
}
inline int dfs(int x,int maxflow)
{if(x==t||!maxflow)return maxflow;vis[x]=clk;int res=0,f;for(register int &i=cur[x];i;i=nex[i])if((vis[x]^vis[to[i]])&&cap[i]&&level[to[i]]==level[x]+was[i]){f=dfs(to[i],min(maxflow,cap[i]));res+=f;cap[i]-=f;cap[i^1]+=f;maxflow-=f;ans_was+=f*was[i];if(!maxflow)break;}vis[x]=0;return res;
}
inline int Dinic()
{int res=0;ans_was=0;while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf);ans_was-=5001*res;return res;
}
inline void solve()
{for(register int i=1,tmp;i<=cnt;++i){tmp=G[match[i].x][match[i].y];G[match[i].x][match[i].y]=-1;Build();Dinic();if(-ans_was==stand)M[match[i].x][match[i].y]=0;G[match[i].x][match[i].y]=tmp;}
}
int main()
{read(n);for(register int i=1;i<=n;++i)for(register int j=1;j<=n;++j)read(G[i][j]);s=n+n+1,t=s+1;Build();Dinic();stand=-ans_was;write(stand,'\n');for(register int i=2;i<=n*n*2;i+=2)if(!cap[i])match[++cnt]=(side){out[i],to[i]-n},M[out[i]][to[i]-n]=1;solve();cnt=0;for(register int i=1;i<=n;++i)for(register int j=1;j<=n;++j)if(M[i][j])ans[++cnt]=(side){i,j};std::sort(ans+1,ans+cnt+1);for(register int i=1;i<=cnt;++i)write(ans[i].x,' '),write(ans[i].y,'\n');return 0;
}

转载于:https://www.cnblogs.com/hongyj/p/9116920.html

【刷题】BZOJ 5154 [Tjoi2014]匹配相关推荐

  1. BZOJ刷题记录---提高组难度

    BZOJ刷题记录---提高组难度 总目录详见https://blog.csdn.net/mrcrack/article/details/90228694 序号 题号 算法 思想难度 实现难度 总难度 ...

  2. BZOJ 2135 刷题计划(贪心,求导,二分)【BZOJ 修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2135 是 hydro 的 BZOJ ...

  3. 【刷题】BZOJ 4176 Lucas的数论

    Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目"求Sigma(f(i)),其中1<=i< ...

  4. BZOJ第一页刷题计划

    BZOJ第一页刷题计划 已完成:67 / 90 [BZOJ1000]A+B Problem:A+B: [BZOJ1001][BeiJing2006]狼抓兔子:最小割: [BZOJ1002][FJOI2 ...

  5. ​LeetCode刷题实战524:通过删除字母匹配到字典里最长单词

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  6. ACM比赛经验、刷题记录及模板库总结(更新中)

    前言 本文所提及的部分题目代码,可以在我的Github上找到 第一部分 经验分享及感受 第二部分 刷题记录 一.基础算法&程序语言 //strlen()函数的复杂度是O(n)要小心 //截取字 ...

  7. LeetCode刷题记录11——290. Word Pattern(easy)

    LeetCode刷题记录11--290. Word Pattern(easy) 目录 LeetCode刷题记录11--290. Word Pattern(easy) 题目 语言 思路 源码 后记 题目 ...

  8. 你面试稳了!通关LeetCode刷题完整攻略,省时又高效

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 作者:穷码农 来源:https://zhuanlan.zhihu.com/p/10 ...

  9. 机器学习 - 竞赛网站,算法刷题网站

    数据竞赛类网站 Kaggle 阿里巴巴天池大数据比赛 DataCastle CCF大数据与计算智能大赛 Di-Tech算法大赛 KDD-Cup KDnuggets Competition 全国高校云计 ...

最新文章

  1. 如何将代码优雅的放在WORD文档中?
  2. 轴对称 Navier-Stokes 方程组的点态正则性准则 I
  3. java 文本编辑器 源码_java文本编辑器源码
  4. SAP CRM事务码COMMPR01无法搜索Individual Object
  5. 美团刚做起网约车,滴滴就送外卖?你们倒真是相爱相杀
  6. Android--获取当前系统的语言环境
  7. PASCAL VOC 2012 dataset、 云盘分享
  8. MikroTik RB750r2/RB750gr3 操作记录
  9. 计算机组装与维修第3版,计算机组装与维护(第3版)
  10. 童年经典,任天堂switch红白机游戏
  11. 替代SSD?Crossbar进军中国存储市场
  12. 常见的几种ADSL 路由器的端口映射方法
  13. 和数集团首款自研虚拟数字人上线,“始祖龙”带你跨山海,链未来
  14. 按光在光纤中的传输模式可将光纤分为单模光纤和多模光纤两种
  15. matlab 保存当前图像,Matlab保存图像的方法总结
  16. odoo企业版与社区版区别(odoo14企业版)
  17. 嵌入式Linux驱动学习【8】—— Nand Flash
  18. 画世界怎么用光影_【色彩】色彩绘画时四种光影的运用~
  19. 电脑怎么卸载软件?彻底卸载软件,4个方法分享
  20. EasyRecovery15易恢复新版数据恢复软件

热门文章

  1. 广义矩估计的一般步骤_【基本无害】动态理性预期理论与广义矩估计02
  2. 如何在自己开发的日程管理页面插入提醒功能_给大家推荐一款高颜值的日程管理类APP...
  3. java 拖放文字_Java实现拖放效果
  4. iphone照片永久删除怎么恢复_微信数据怎么永久删除不被恢复?只删除聊天记录没用,打开这里彻底删除!...
  5. 我的世界自己服务器显示坐标,如何让我的世界一直显示坐标 | 手游网游页游攻略大全...
  6. java 挥发注解_C中的挥发性预选赛
  7. jsf用于页面判断的标签_JSF –在JSF视图页面中添加标签,图像,按钮和文本字段
  8. Nuxt使用cookies踩坑之设置axios的header
  9. 二:C#对象、集合、DataTable与Json内容互转示例;
  10. js 判断各种数据类型